From 3cbfba02fef9dae07a041fdbf2e89611d72d6f90 Mon Sep 17 00:00:00 2001 From: David Wei Date: Mon, 12 Jan 2015 09:37:20 +0000 Subject: [PATCH] Upload BSD-licensed Vlv2TbltDevicePkg and Vlv2DeviceRefCodePkg to https://svn.code.sf.net/p/edk2/code/trunk/edk2/, which are for MinnowBoard MAX open source project. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: David Wei Reviewed-by: Mike Wu Reviewed-by: Hot Tian git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16599 6f19259b-4bc3-4df7-8a09-765794883524 --- .../AcpiTablesPCAT/98_LINK.ASL | 623 +++ .../AcpiTablesPCAT/AcpiTablePlatform.h | 76 + .../AcpiTablesPCAT/AcpiTables.inf | 44 + Vlv2DeviceRefCodePkg/AcpiTablesPCAT/CPU.asl | 55 + Vlv2DeviceRefCodePkg/AcpiTablesPCAT/DSDT.ASL | 81 + .../AcpiTablesPCAT/Facp/Facp.aslc | 194 + .../AcpiTablesPCAT/Facs/Facs.aslc | 90 + .../AcpiTablesPCAT/GloblNvs.asl | 352 ++ Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Gpe.asl | 105 + .../AcpiTablesPCAT/HOST_BUS.ASL | 353 ++ .../AcpiTablesPCAT/Hpet/Hpet.aslc | 69 + .../AcpiTablesPCAT/INTELGFX.ASL | 885 +++ .../AcpiTablesPCAT/INTELISPDev2.ASL | 77 + .../AcpiTablesPCAT/IgdOGBDA.ASL | 161 + .../AcpiTablesPCAT/IgdOMOBF.ASL | 491 ++ .../AcpiTablesPCAT/IgdOSBCB.ASL | 280 + .../AcpiTablesPCAT/IgdOpRn.ASL | 305 ++ .../AcpiTablesPCAT/IoTVirtualDevice.asl | 177 + .../AcpiTablesPCAT/LPC_DEV.ASL | 157 + Vlv2DeviceRefCodePkg/AcpiTablesPCAT/LpcB.asl | 65 + .../AcpiTablesPCAT/Lpit/Lpit.aslc | 229 + .../AcpiTablesPCAT/Madt/Madt.h | 195 + .../AcpiTablesPCAT/Madt/Madt30.aslc | 184 + .../AcpiTablesPCAT/Mcfg/Mcfg.aslc | 92 + .../AcpiTablesPCAT/PCI_DRC.ASL | 96 + Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Pch.asl | 685 +++ .../AcpiTablesPCAT/PchAudio.asl | 42 + .../AcpiTablesPCAT/PchEhci.asl | 275 + .../AcpiTablesPCAT/PchLpss.asl | 1096 ++++ .../AcpiTablesPCAT/PchPcie.asl | 56 + .../AcpiTablesPCAT/PchScc.asl | 616 +++ .../AcpiTablesPCAT/PchSmb.asl | 839 +++ .../AcpiTablesPCAT/PchXhci.asl | 385 ++ .../AcpiTablesPCAT/PciTree.asl | 373 ++ .../AcpiTablesPCAT/Platform.asl | 830 +++ Vlv2DeviceRefCodePkg/AcpiTablesPCAT/RTD3.asl | 203 + .../AcpiTablesPCAT/THERMAL.ASL | 138 + .../AcpiTablesPCAT/UsbSbd.asl | 99 + Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Video.asl | 40 + Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Vlv.asl | 45 + Vlv2DeviceRefCodePkg/AcpiTablesPCAT/token.asl | 45 + .../Guid/Vlv2DeviceRefCodePkgTokenSpace.h | 30 + .../Guid/PowerManagementAcpiTableStorage.h | 33 + .../CPU/Include/Ppi/VlvPolicy.h | 110 + .../CPU/Include/Protocol/PpmPlatformPolicy.h | 138 + .../ValleyView2Soc/CPU/Include/Types.h | 61 + .../AcpiTables/PowerManagementAcpiTables.inf | 45 + .../PowerManagement/AcpiTables/Ssdt/ApCst.asl | 116 + .../PowerManagement/AcpiTables/Ssdt/ApIst.asl | 172 + .../PowerManagement/AcpiTables/Ssdt/ApTst.asl | 268 + .../AcpiTables/Ssdt/Cpu0Cst.asl | 280 + .../AcpiTables/Ssdt/Cpu0Ist.asl | 266 + .../AcpiTables/Ssdt/Cpu0Tst.asl | 241 + .../PowerManagement/AcpiTables/Ssdt/CpuPm.asl | 799 +++ .../Include/PlatformBaseAddresses.h | 98 + .../NorthCluster/Include/Ppi/Capsule.h | 66 + .../Include/Ppi/PlatformMemoryRange.h | 150 + .../Include/Ppi/PlatformMemorySize.h | 52 + .../NorthCluster/Include/Ppi/SmmAccess.h | 171 + .../NorthCluster/Include/Ppi/VlvMmioPolicy.h | 45 + .../NorthCluster/Include/Ppi/VlvPeiInit.h | 41 + .../NorthCluster/Include/Ppi/VlvPolicy.h | 112 + .../Include/Protocol/IgdOpRegion.h | 219 + .../NorthCluster/Include/Protocol/MemInfo.h | 89 + .../Include/Protocol/PlatformGopPolicy.h | 73 + .../Include/Protocol/VlvPlatformPolicy.h | 111 + .../NorthCluster/Include/Valleyview.h | 61 + .../NorthCluster/Include/VlvAccess.h | 260 + .../Include/VlvCommonDefinitions.h | 258 + .../SouthCluster/Include/Guid/PchInitVar.h | 54 + .../Include/Guid/SataControllerGuid.h | 40 + .../SouthCluster/Include/Guid/SmbusArpMap.h | 36 + .../SouthCluster/Include/Guid/Vlv2Variable.h | 34 + .../Include/IndustryStandard/CeAta.h | 132 + .../Include/IndustryStandard/Mmc.h | 355 ++ .../Include/IndustryStandard/SdCard.h | 163 + .../SouthCluster/Include/Library/I2CLib.h | 175 + .../Include/Library/PchPlatformLib.h | 121 + .../SouthCluster/Include/PchAccess.h | 526 ++ .../Include/PchCommonDefinitions.h | 216 + .../SouthCluster/Include/PchRegs.h | 211 + .../SouthCluster/Include/PchRegs/PchRegsHda.h | 56 + .../Include/PchRegs/PchRegsLpss.h | 492 ++ .../Include/PchRegs/PchRegsPcie.h | 89 + .../SouthCluster/Include/PchRegs/PchRegsPcu.h | 1205 +++++ .../Include/PchRegs/PchRegsRcrb.h | 54 + .../Include/PchRegs/PchRegsSata.h | 251 + .../SouthCluster/Include/PchRegs/PchRegsScc.h | 59 + .../Include/PchRegs/PchRegsSmbus.h | 155 + .../SouthCluster/Include/PchRegs/PchRegsSpi.h | 119 + .../SouthCluster/Include/PchRegs/PchRegsUsb.h | 98 + .../SouthCluster/Include/Ppi/PchInit.h | 81 + .../SouthCluster/Include/Ppi/PchPeiInit.h | 40 + .../Include/Ppi/PchPlatformPolicy.h | 167 + .../SouthCluster/Include/Ppi/PchUsbPolicy.h | 75 + .../SouthCluster/Include/Ppi/PeiBlockIo.h | 236 + .../SouthCluster/Include/Ppi/Sdhc.h | 365 ++ .../SouthCluster/Include/Ppi/SmbusPolicy.h | 46 + .../SouthCluster/Include/Ppi/Spi.h | 48 + .../Include/Protocol/ActiveBios.h | 129 + .../Include/Protocol/ActiveBiosProtocol.h | 131 + .../Protocol/DxePchPolicyUpdateProtocol.h | 57 + .../Include/Protocol/EmmcCardInfoProtocol.h | 48 + .../SouthCluster/Include/Protocol/Gpio.h | 167 + .../Include/Protocol/HwWatchdogTimer.h | 300 ++ .../SouthCluster/Include/Protocol/I2cBus.h | 170 + .../Include/Protocol/PchExtendedReset.h | 90 + .../SouthCluster/Include/Protocol/PchInfo.h | 66 + .../Include/Protocol/PchPlatformPolicy.h | 556 ++ .../SouthCluster/Include/Protocol/PchReset.h | 120 + .../Include/Protocol/PchS3Support.h | 138 + .../SouthCluster/Include/Protocol/SdHostIo.h | 415 ++ .../Include/Protocol/SmbiosSlotPopulation.h | 53 + .../Include/Protocol/SmmIchnDispatchEx.h | 165 + .../SouthCluster/Include/Protocol/SmmSmbus.h | 45 + .../SouthCluster/Include/Protocol/Spi.h | 266 + .../SouthCluster/Include/Protocol/TcoReset.h | 94 + .../SouthCluster/Include/Rsci.h | 34 + .../SouthCluster/Include/TianoApi.h | 67 + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec | 121 + Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.c | 1307 +++++ Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.h | 224 + .../AcpiPlatform/AcpiPlatform.inf | 90 + .../AcpiPlatform/AcpiPlatformHooks.c | 500 ++ .../AcpiPlatform/AcpiPlatformHooks.h | 132 + .../AcpiPlatform/AcpiPlatformHooksLib.h | 96 + Vlv2TbltDevicePkg/AcpiPlatform/Osfr.h | 61 + .../FirmwareUpdate/FirmwareUpdate.c | 927 ++++ .../FirmwareUpdate/FirmwareUpdate.h | 190 + .../FirmwareUpdate/FirmwareUpdate.inf | 90 + .../FirmwareUpdate/FirmwareUpdateStrings.uni | Bin 0 -> 7472 bytes Vlv2TbltDevicePkg/BfmLib.exe | Bin 0 -> 499712 bytes Vlv2TbltDevicePkg/BiosIdD.env | 30 + Vlv2TbltDevicePkg/BiosIdR.env | 30 + Vlv2TbltDevicePkg/BiosIdx64D.env | 30 + Vlv2TbltDevicePkg/BiosIdx64R.env | 30 + .../BootScriptSaveDxe/BootScriptSaveDxe.inf | 65 + .../InternalBootScriptSave.h | 107 + .../BootScriptSaveDxe/ScriptSave.c | 631 +++ Vlv2TbltDevicePkg/Build_IFWI.bat | 178 + Vlv2TbltDevicePkg/Build_IFWI.sh | 101 + Vlv2TbltDevicePkg/FCE.exe | Bin 0 -> 630784 bytes .../FspAzaliaConfigData/AzaliaConfig.bin | Bin 0 -> 3708 bytes .../FspSupport/BootModePei/BootModePei.c | 48 + .../FspSupport/BootModePei/BootModePei.inf | 45 + .../FspHobProcessLibVlv2.c | 387 ++ .../FspHobProcessLibVlv2.inf | 79 + .../FspPlatformSecLibVlv2.c | 150 + .../FspPlatformSecLibVlv2.inf | 87 + .../Ia32/AsmSaveSecContext.asm | 51 + .../SecFspPlatformSecLibVlv2/Ia32/Fsp.inc | 51 + .../Ia32/PeiCoreEntry.asm | 141 + .../Ia32/SecEntry.asm | 344 ++ .../SecFspPlatformSecLibVlv2/Ia32/Stack.S | 77 + .../SecFspPlatformSecLibVlv2/Ia32/Stack.asm | 82 + .../SecFspPlatformSecLibVlv2/PlatformInit.c | 42 + .../SecFspPlatformSecLibVlv2/SaveSecContext.c | 114 + .../SecGetPerformance.c | 89 + .../SecPlatformInformation.c | 83 + .../SecFspPlatformSecLibVlv2/SecRamInitData.c | 22 + .../SecTempRamSupport.c | 155 + .../SecFspPlatformSecLibVlv2/UartInit.c | 198 + Vlv2TbltDevicePkg/FvInfoPei/FvInfoPei.c | 73 + Vlv2TbltDevicePkg/FvInfoPei/FvInfoPei.inf | 54 + Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbInfo.c | 175 + .../FvbRuntimeDxe/FvbRuntimeDxe.inf | 85 + Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.c | 1114 ++++ Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.h | 187 + .../FvbRuntimeDxe/FvbServiceDxe.c | 204 + .../FvbRuntimeDxe/FvbServiceSmm.c | 132 + Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmm.inf | 87 + .../FvbRuntimeDxe/FvbSmmCommon.h | 78 + Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.c | 949 ++++ Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.h | 237 + Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.inf | 55 + Vlv2TbltDevicePkg/GenBiosId | Bin 0 -> 12236 bytes Vlv2TbltDevicePkg/GenBiosId.exe | Bin 0 -> 384000 bytes .../Include/AlertStandardFormatTable.h | 127 + Vlv2TbltDevicePkg/Include/ChipsetAccess.h | 33 + Vlv2TbltDevicePkg/Include/CommonIncludes.h | 120 + Vlv2TbltDevicePkg/Include/CpuType.h | 64 + Vlv2TbltDevicePkg/Include/FileHandleLib.h | 504 ++ .../Include/Guid/AcpiTableStorage.h | 35 + .../Include/Guid/AlertStandardFormat.h | 91 + Vlv2TbltDevicePkg/Include/Guid/BiosId.h | 35 + .../Include/Guid/BoardFeatures.h | 219 + Vlv2TbltDevicePkg/Include/Guid/EfiVpdData.h | 161 + Vlv2TbltDevicePkg/Include/Guid/FirmwareId.h | 66 + .../Include/Guid/HwWatchdogTimerHob.h | 139 + Vlv2TbltDevicePkg/Include/Guid/IdccData.h | 109 + Vlv2TbltDevicePkg/Include/Guid/ItkData.h | 75 + .../Include/Guid/MemoryConfigData.h | 37 + Vlv2TbltDevicePkg/Include/Guid/OsSelection.h | 90 + Vlv2TbltDevicePkg/Include/Guid/PciLanInfo.h | 44 + .../Include/Guid/PlatformCpuInfo.h | 185 + Vlv2TbltDevicePkg/Include/Guid/PlatformInfo.h | 437 ++ .../Include/Guid/SensorInfoVariable.h | 284 + .../Include/Guid/SetupVariable.h | 1351 +++++ Vlv2TbltDevicePkg/Include/Hpet.h | 45 + Vlv2TbltDevicePkg/Include/Library/BiosIdLib.h | 109 + Vlv2TbltDevicePkg/Include/Library/CpuIA32.h | 350 ++ .../Include/Library/EfiRegTableLib.h | 201 + Vlv2TbltDevicePkg/Include/Library/Esrt.h | 79 + Vlv2TbltDevicePkg/Include/Library/Fd.h | 269 + .../Include/Library/FlashDeviceLib.h | 127 + .../Include/Library/I2cMmioConfigLib.h | 28 + .../Include/Library/I2cPort_platform.h | 31 + .../Include/Library/PlatformFsaLib.h | 55 + .../Include/Library/PlatformFspLib.h | 28 + Vlv2TbltDevicePkg/Include/Library/SpiFlash.H | 244 + .../Include/Library/StallSmmLib.h | 45 + .../Include/Library/UsbDeviceModeLib.h | 186 + Vlv2TbltDevicePkg/Include/Mcfg.h | 74 + Vlv2TbltDevicePkg/Include/McfgTable.h | 70 + Vlv2TbltDevicePkg/Include/Platform.h | 138 + Vlv2TbltDevicePkg/Include/PlatformBootMode.h | 40 + .../Include/PlatformDefinitions.h | 48 + Vlv2TbltDevicePkg/Include/Ppi/MfgMemoryTest.h | 47 + Vlv2TbltDevicePkg/Include/Ppi/Sha256Hash.h | 136 + Vlv2TbltDevicePkg/Include/Ppi/Speaker.h | 70 + Vlv2TbltDevicePkg/Include/Ppi/UsbController.h | 90 + .../Include/Protocol/CK505ClockPlatformInfo.h | 131 + .../Include/Protocol/EnhancedSpeedstep.h | 81 + .../Include/Protocol/GlobalNvsArea.h | 484 ++ .../Include/Protocol/HwWatchdogTimer.h | 240 + Vlv2TbltDevicePkg/Include/Protocol/I2cAcpi.h | 112 + Vlv2TbltDevicePkg/Include/Protocol/I2cBus.h | 169 + .../Include/Protocol/I2cBusMcg.h | 168 + .../Include/Protocol/I2cHostMcg.h | 143 + .../Include/Protocol/I2cMasterMcg.h | 524 ++ Vlv2TbltDevicePkg/Include/Protocol/I2cSlave.h | 199 + .../Include/Protocol/LpcWpc83627Policy.h | 97 + .../Include/Protocol/LpcWpce791Policy.h | 60 + .../Include/Protocol/MmioDevice.h | 89 + .../Include/Protocol/Observable.h | 191 + .../Include/Protocol/PlatformGopPolicy.h | 73 + .../Include/Protocol/PlatformIdeInit.h | 48 + .../Include/Protocol/SetupMode.h | 84 + .../Include/Protocol/SmbiosSlotPopulation.h | 52 + Vlv2TbltDevicePkg/Include/Protocol/Speaker.h | 70 + Vlv2TbltDevicePkg/Include/Protocol/TcoReset.h | 72 + Vlv2TbltDevicePkg/Include/Protocol/TpmMp.h | 141 + .../Include/Protocol/UsbPolicy.h | 131 + .../Include/Protocol/VlvPlatformPolicy.h | 108 + Vlv2TbltDevicePkg/Include/SetupMode.h | 90 + .../IntelGopDepex/IntelGopDriver.depex | 1 + .../Library/BiosIdLib/BiosIdLib.c | 342 ++ .../Library/BiosIdLib/BiosIdLib.inf | 55 + .../Library/CpuIA32Lib/CpuIA32Lib.inf | 46 + .../Library/CpuIA32Lib/EfiCpuVersion.c | 75 + .../Library/CpuIA32Lib/IA32/CpuIA32.S | 228 + .../Library/CpuIA32Lib/IA32/CpuIA32.asm | 211 + .../Library/CpuIA32Lib/IA32/CpuIA32.c | 182 + .../Library/CpuIA32Lib/X64/Cpu.S | 212 + .../Library/CpuIA32Lib/X64/Cpu.asm | 227 + .../Library/EfiRegTableLib/EfiRegTableLib.c | 287 + .../Library/EfiRegTableLib/EfiRegTableLib.inf | 52 + .../Library/FlashDeviceLib/FlashDeviceLib.c | 467 ++ .../Library/FlashDeviceLib/FlashDeviceLib.inf | 50 + .../FlashDeviceLib/SpiChipDefinitions.h | 840 +++ Vlv2TbltDevicePkg/Library/I2CLib/I2CLib.c | 51 + .../Library/I2CLib/I2CLibNull.inf | 53 + .../IntelPchAcpiTimerLib/CommonHeader.h | 32 + .../IntelPchAcpiTimerLib.c | 260 + .../IntelPchAcpiTimerLib.inf | 56 + .../BoardClkGens/BoardClkGens.c | 426 ++ .../BoardClkGens/BoardClkGens.h | 260 + .../MultiPlatformLib/BoardGpios/BoardGpios.c | 535 ++ .../MultiPlatformLib/BoardGpios/BoardGpios.h | 329 ++ .../BoardJumpers/BoardJumpers.c | 35 + .../BoardJumpers/BoardJumpers.h | 35 + .../BoardOemIds/BoardOemIds.c | 47 + .../BoardOemIds/BoardOemIds.h | 34 + .../BoardSsidSvid/BoardSsidSvid.c | 42 + .../BoardSsidSvid/BoardSsidSvid.h | 40 + .../MultiPlatformLib/MultiPlatformLib.c | 122 + .../MultiPlatformLib/MultiPlatformLib.h | 94 + .../MultiPlatformLib/MultiPlatformLib.inf | 83 + .../MultiPlatformLib/PlatformInfoHob.c | 59 + .../Library/PchPlatformLib/PchPlatformLib.inf | 55 + .../PchPlatformLib/PchPlatformLibrary.c | 131 + .../PchPlatformLib/PchPlatformLibrary.h | 40 + .../Library/PchSmmLib/CommonHeader.h | 37 + .../Library/PchSmmLib/PchSmmLib.c | 162 + .../Library/PchSmmLib/PchSmmLib.inf | 51 + .../Library/PlatformBdsLib/BdsPlatform.c | 2399 +++++++++ .../Library/PlatformBdsLib/BdsPlatform.h | 484 ++ .../Library/PlatformBdsLib/PlatformBdsLib.inf | 118 + .../Library/PlatformBdsLib/PlatformData.c | 265 + .../Library/PlatformCmosLib/PlatformCmosLib.c | 111 + .../PlatformCmosLib/PlatformCmosLib.inf | 35 + .../Library/PlatformFspLib/PlatformFspLib.c | 49 + .../Library/PlatformFspLib/PlatformFspLib.inf | 54 + .../Library/ResetSystemLib/ResetSystemLib.c | 178 + .../Library/ResetSystemLib/ResetSystemLib.inf | 52 + .../SerialPortLib/PlatformSerialPortLib.h | 69 + .../Library/SerialPortLib/SerialPortLib.c | 262 + .../Library/SerialPortLib/SerialPortLib.inf | 57 + .../Library/SerialPortLib/SioInit.c | 132 + .../Library/SerialPortLib/SioInit.h | 78 + .../Library/SmbusLib/CommonHeader.h | 31 + Vlv2TbltDevicePkg/Library/SmbusLib/SmbusLib.c | 878 +++ .../Library/SmbusLib/SmbusLib.inf | 51 + .../Library/StallSmmLib/StallSmm.c | 94 + .../Library/StallSmmLib/StallSmmLib.inf | 56 + Vlv2TbltDevicePkg/Logo/Logo.bmp | Bin 0 -> 94434 bytes Vlv2TbltDevicePkg/Metronome/LegacyMetronome.c | 190 + Vlv2TbltDevicePkg/Metronome/LegacyMetronome.h | 69 + Vlv2TbltDevicePkg/Metronome/Metronome.inf | 54 + .../MonoStatusCode/EfiStatusCode.h | 183 + .../MonoStatusCode/MonoStatusCode.c | 137 + .../MonoStatusCode/MonoStatusCode.h | 133 + .../MonoStatusCode/MonoStatusCode.inf | 78 + .../MonoStatusCode/PeiPostCode.c | 126 + .../MonoStatusCode/PlatformStatusCode.c | 386 ++ .../MonoStatusCode/PlatformStatusCode.h | 207 + .../Library/GenericBdsLib/BdsBoot.c | 4310 +++++++++++++++ .../Library/GenericBdsLib/BdsConnect.c | 435 ++ .../Library/GenericBdsLib/BdsConsole.c | 1302 +++++ .../Library/GenericBdsLib/BdsMisc.c | 1484 +++++ .../Library/GenericBdsLib/DevicePath.c | 33 + .../Library/GenericBdsLib/GenericBdsLib.inf | 114 + .../GenericBdsLib/GenericBdsStrings.uni | Bin 0 -> 3868 bytes .../Library/GenericBdsLib/InternalBdsLib.h | 150 + .../Library/GenericBdsLib/Performance.c | 358 ++ .../Library/GenericBdsLib/String.c | 32 + .../Library/GenericBdsLib/String.h | 48 + .../Console/ConSplitterDxe/ComponentName.c | 776 +++ .../Console/ConSplitterDxe/ConSplitter.c | 4776 +++++++++++++++++ .../Console/ConSplitterDxe/ConSplitter.h | 2004 +++++++ .../Console/ConSplitterDxe/ConSplitterDxe.inf | 96 + .../ConSplitterDxe/ConSplitterGraphics.c | 628 +++ .../PciPlatform/BoardPciPlatform.c | 60 + Vlv2TbltDevicePkg/PciPlatform/PciPlatform.c | 361 ++ Vlv2TbltDevicePkg/PciPlatform/PciPlatform.h | 88 + Vlv2TbltDevicePkg/PciPlatform/PciPlatform.inf | 70 + .../PlatformCpuInfoDxe/PlatformCpuInfoDxe.c | 65 + .../PlatformCpuInfoDxe/PlatformCpuInfoDxe.h | 34 + .../PlatformCpuInfoDxe/PlatformCpuInfoDxe.inf | 61 + .../PlatformDxe/AzaliaVerbTable.h | 252 + Vlv2TbltDevicePkg/PlatformDxe/BoardId.c | 228 + Vlv2TbltDevicePkg/PlatformDxe/BoardIdDecode.c | 134 + Vlv2TbltDevicePkg/PlatformDxe/BoardIdDecode.h | 66 + Vlv2TbltDevicePkg/PlatformDxe/ClockControl.c | 207 + Vlv2TbltDevicePkg/PlatformDxe/Configuration.h | 697 +++ Vlv2TbltDevicePkg/PlatformDxe/ExI.c | 83 + .../PlatformDxe/IchPlatformPolicy.c | 496 ++ Vlv2TbltDevicePkg/PlatformDxe/IchRegTable.c | 141 + Vlv2TbltDevicePkg/PlatformDxe/IchTcoReset.c | 216 + Vlv2TbltDevicePkg/PlatformDxe/IdccInfo.c | 77 + Vlv2TbltDevicePkg/PlatformDxe/LegacySpeaker.c | 166 + Vlv2TbltDevicePkg/PlatformDxe/LegacySpeaker.h | 74 + .../PlatformDxe/Observable/Observable.c | 587 ++ .../PlatformDxe/Observable/Observable.h | 142 + Vlv2TbltDevicePkg/PlatformDxe/PciBus.h | 384 ++ Vlv2TbltDevicePkg/PlatformDxe/PciDevice.c | 517 ++ Vlv2TbltDevicePkg/PlatformDxe/Platform.c | 1661 ++++++ Vlv2TbltDevicePkg/PlatformDxe/PlatformDxe.h | 719 +++ Vlv2TbltDevicePkg/PlatformDxe/PlatformDxe.inf | 145 + Vlv2TbltDevicePkg/PlatformDxe/SensorVar.c | 117 + .../PlatformDxe/SioPlatformPolicy.c | 87 + Vlv2TbltDevicePkg/PlatformDxe/SlotConfig.c | 153 + Vlv2TbltDevicePkg/PlatformDxe/SlotConfig.h | 85 + .../PlatformGopPolicy/PlatformGopPolicy.c | 196 + .../PlatformGopPolicy/PlatformGopPolicy.inf | 56 + .../PlatformInfoDxe/PlatformInfoDxe.c | 161 + .../PlatformInfoDxe/PlatformInfoDxe.h | 35 + .../PlatformInfoDxe/PlatformInfoDxe.inf | 57 + Vlv2TbltDevicePkg/PlatformInitPei/BootMode.c | 426 ++ .../PlatformInitPei/CpuInitPeim.c | 49 + Vlv2TbltDevicePkg/PlatformInitPei/Dimm.c | 324 ++ Vlv2TbltDevicePkg/PlatformInitPei/FlashMap.c | 148 + .../PlatformInitPei/LegacySpeaker.c | 173 + .../PlatformInitPei/LegacySpeaker.h | 76 + Vlv2TbltDevicePkg/PlatformInitPei/MchInit.c | 77 + .../PlatformInitPei/MemoryCallback.c | 345 ++ .../PlatformInitPei/MemoryPeim.c | 369 ++ .../PlatformInitPei/PchInitPeim.c | 813 +++ .../PlatformInitPei/PlatformEarlyInit.c | 1034 ++++ .../PlatformInitPei/PlatformEarlyInit.h | 1502 ++++++ .../PlatformInitPei/PlatformInfoInit.c | 186 + .../PlatformInitPei/PlatformInitPei.inf | 122 + .../PlatformInitPei/PlatformSsaInitPeim.c | 63 + Vlv2TbltDevicePkg/PlatformInitPei/Recovery.c | 366 ++ Vlv2TbltDevicePkg/PlatformInitPei/Stall.c | 96 + Vlv2TbltDevicePkg/PlatformPei/BootMode.c | 403 ++ Vlv2TbltDevicePkg/PlatformPei/CommonHeader.h | 65 + .../PlatformPei/MemoryCallback.c | 160 + Vlv2TbltDevicePkg/PlatformPei/Platform.c | 1063 ++++ Vlv2TbltDevicePkg/PlatformPei/Platform.h | 216 + Vlv2TbltDevicePkg/PlatformPei/PlatformPei.inf | 136 + Vlv2TbltDevicePkg/PlatformPei/Stall.c | 95 + Vlv2TbltDevicePkg/PlatformPkg.dec | 208 + Vlv2TbltDevicePkg/PlatformPkg.fdf | 1105 ++++ Vlv2TbltDevicePkg/PlatformPkgConfig.dsc | 96 + Vlv2TbltDevicePkg/PlatformPkgGcc.fdf | 1037 ++++ Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc | 1492 +++++ Vlv2TbltDevicePkg/PlatformPkgIA32.dsc | 1480 +++++ Vlv2TbltDevicePkg/PlatformPkgX64.dsc | 1480 +++++ Vlv2TbltDevicePkg/PlatformSetupDxe/Boot.vfi | 77 + .../PlatformSetupDxe/Configuration.h | 61 + .../PlatformSetupDxe/DebugConfig.vfi | 123 + .../PlatformSetupDxe/FwVersionStrings.uni | Bin 0 -> 4108 bytes Vlv2TbltDevicePkg/PlatformSetupDxe/Main.vfi | 336 ++ .../PlatformSetupDxe/PlatformSetupDxe.c | 933 ++++ .../PlatformSetupDxe/PlatformSetupDxe.h | 102 + .../PlatformSetupDxe/PlatformSetupDxe.inf | 145 + .../PlatformSetupDxe/Security.vfi | 96 + .../PlatformSetupDxe/SetupFunctions.c | 90 + .../PlatformSetupDxe/SetupInfoRecords.c | 1865 +++++++ .../PlatformSetupDxe/SouthClusterConfig.vfi | 918 ++++ .../PlatformSetupDxe/SystemComponent.vfi | 86 + .../PlatformSetupDxe/Thermal.vfi | 83 + Vlv2TbltDevicePkg/PlatformSetupDxe/UnCore.vfi | 240 + .../PlatformSetupDxe/UqiList.uni | Bin 0 -> 65892 bytes Vlv2TbltDevicePkg/PlatformSetupDxe/Vfr.vfr | 128 + .../PlatformSetupDxe/VfrStrings.uni | Bin 0 -> 214022 bytes Vlv2TbltDevicePkg/PlatformSmm/Platform.c | 977 ++++ Vlv2TbltDevicePkg/PlatformSmm/PlatformSmm.inf | 98 + Vlv2TbltDevicePkg/PlatformSmm/S3Save.c | 382 ++ Vlv2TbltDevicePkg/PlatformSmm/SmmPlatform.h | 245 + Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.c | 257 + Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.h | 55 + Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.c | 160 + Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.h | 46 + Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.inf | 55 + .../SaveMemoryConfig/SaveMemoryConfig.c | 187 + .../SaveMemoryConfig/SaveMemoryConfig.h | 72 + .../SaveMemoryConfig/SaveMemoryConfig.inf | 66 + .../SmBiosMiscDxe/CommonHeader.h | 44 + .../MiscBaseBoardManufacturer.uni | Bin 0 -> 2866 bytes .../MiscBaseBoardManufacturerData.c | 63 + .../MiscBaseBoardManufacturerFunction.c | 232 + .../SmBiosMiscDxe/MiscBiosVendor.uni | Bin 0 -> 1860 bytes .../SmBiosMiscDxe/MiscBiosVendorData.c | 106 + .../SmBiosMiscDxe/MiscBiosVendorFunction.c | 341 ++ .../SmBiosMiscDxe/MiscBootInformationData.c | 39 + .../MiscBootInformationFunction.c | 87 + .../SmBiosMiscDxe/MiscChassisManufacturer.uni | Bin 0 -> 2056 bytes .../MiscChassisManufacturerData.c | 62 + .../MiscChassisManufacturerFunction.c | 155 + .../SmBiosMiscDxe/MiscMemoryDevice.uni | Bin 0 -> 2904 bytes .../SmBiosMiscDxe/MiscMemoryDeviceData.c | 50 + .../SmBiosMiscDxe/MiscMemoryDeviceFunction.c | 324 ++ .../MiscNumberOfInstallableLanguagesData.c | 43 + ...MiscNumberOfInstallableLanguagesFunction.c | 254 + .../SmBiosMiscDxe/MiscOemString.uni | Bin 0 -> 1848 bytes .../SmBiosMiscDxe/MiscOemStringData.c | 39 + .../SmBiosMiscDxe/MiscOemStringFunction.c | 94 + .../SmBiosMiscDxe/MiscOemType0x90.uni | Bin 0 -> 2078 bytes .../SmBiosMiscDxe/MiscOemType0x90Data.c | 41 + .../SmBiosMiscDxe/MiscOemType0x90Function.c | 452 ++ .../SmBiosMiscDxe/MiscOemType0x94.uni | Bin 0 -> 4302 bytes .../SmBiosMiscDxe/MiscOemType0x94Data.c | 59 + .../SmBiosMiscDxe/MiscOemType0x94Function.c | 1223 +++++ .../SmBiosMiscDxe/MiscOnboardDevice.uni | Bin 0 -> 1910 bytes .../SmBiosMiscDxe/MiscOnboardDeviceData.c | 53 + .../SmBiosMiscDxe/MiscOnboardDeviceFunction.c | 140 + .../SmBiosMiscDxe/MiscPhysicalArray.uni | Bin 0 -> 1518 bytes .../SmBiosMiscDxe/MiscPhysicalArrayData.c | 43 + .../SmBiosMiscDxe/MiscPhysicalArrayFunction.c | 106 + .../MiscPortInternalConnectorDesignator.uni | Bin 0 -> 2566 bytes .../MiscPortInternalConnectorDesignatorData.c | 61 + ...cPortInternalConnectorDesignatorFunction.c | 157 + .../SmBiosMiscDxe/MiscProcessorCache.uni | Bin 0 -> 1506 bytes .../SmBiosMiscDxe/MiscProcessorCacheData.c | 38 + .../MiscProcessorCacheFunction.c | 202 + .../MiscProcessorInformation.uni | Bin 0 -> 2208 bytes .../MiscProcessorInformationData.c | 76 + .../MiscProcessorInformationFunction.c | 455 ++ .../SmBiosMiscDxe/MiscResetCapabilitiesData.c | 48 + .../MiscResetCapabilitiesFunction.c | 90 + .../SmBiosMiscDxe/MiscSubclassDriver.h | 193 + .../SmBiosMiscDxe/MiscSubclassDriver.uni | Bin 0 -> 2354 bytes .../MiscSubclassDriverDataTable.c | 103 + .../MiscSubclassDriverEntryPoint.c | 174 + .../MiscSystemLanguageString.uni | Bin 0 -> 1576 bytes .../MiscSystemLanguageStringData.c | 39 + .../MiscSystemLanguageStringFunction.c | 98 + .../SmBiosMiscDxe/MiscSystemManufacturer.uni | Bin 0 -> 2478 bytes .../MiscSystemManufacturerData.c | 53 + .../MiscSystemManufacturerFunction.c | 353 ++ .../SmBiosMiscDxe/MiscSystemOptionString.uni | Bin 0 -> 1578 bytes .../MiscSystemOptionStringData.c | 36 + .../MiscSystemOptionStringFunction.c | 98 + .../MiscSystemSlotDesignation.uni | Bin 0 -> 2920 bytes .../MiscSystemSlotDesignationData.c | 251 + .../MiscSystemSlotDesignationFunction.c | 132 + .../SmBiosMiscDxe/SmBiosMiscDxe.inf | 144 + .../SmmSwDispatch2OnSmmSwDispatchThunk.c | 464 ++ .../SmmSwDispatch2OnSmmSwDispatchThunk.inf | 59 + .../SmramSaveInfoHandlerSmm.c | 182 + .../SmramSaveInfoHandlerSmm.inf | 59 + .../Stitch/Gcc/NvStorageFtwSpare.bin | 1 + .../Stitch/Gcc/NvStorageFtwWorking.bin | Bin 0 -> 8192 bytes .../Stitch/Gcc/NvStorageVariable.bin | Bin 0 -> 253952 bytes .../Stitch/IFWIHeader/IFWI_HEADER.bin | Bin 0 -> 4096 bytes .../Stitch/IFWIHeader/Vacant.bin | 1 + Vlv2TbltDevicePkg/Stitch/IFWIStitch.bat | 244 + .../Stitch/MNW2_Stitch_Config.txt | 16 + Vlv2TbltDevicePkg/UiApp/FrontPage.c | 38 + Vlv2TbltDevicePkg/UiApp/UiApp.inf | 37 + .../VlvPlatformInitDxe/IgdOpRegion.c | 938 ++++ .../VlvPlatformInitDxe/IgdOpRegion.h | 240 + .../VlvPlatformInitDxe/VlvPlatformInit.c | 292 + .../VlvPlatformInitDxe/VlvPlatformInit.h | 70 + .../VlvPlatformInitDxe/VlvPlatformInitDxe.inf | 79 + Vlv2TbltDevicePkg/Wpce791/LpcDriver.c | 349 ++ Vlv2TbltDevicePkg/Wpce791/LpcDriver.h | 117 + Vlv2TbltDevicePkg/Wpce791/LpcIsaAcpi.c | 371 ++ Vlv2TbltDevicePkg/Wpce791/LpcIsaAcpi.h | 108 + Vlv2TbltDevicePkg/Wpce791/LpcSio.c | 131 + Vlv2TbltDevicePkg/Wpce791/LpcSio.h | 106 + Vlv2TbltDevicePkg/Wpce791/Wpce791.inf | 68 + Vlv2TbltDevicePkg/bldX64.bat | 222 + Vlv2TbltDevicePkg/bld_vlv.bat | 263 + Vlv2TbltDevicePkg/bld_vlv.sh | 235 + Vlv2TbltDevicePkg/cln.sh | 59 + 518 files changed, 118538 insertions(+) create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/98_LINK.ASL create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/AcpiTablePlatform.h create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/AcpiTables.inf create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/CPU.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/DSDT.ASL create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Facp/Facp.aslc create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Facs/Facs.aslc create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/GloblNvs.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Gpe.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/HOST_BUS.ASL create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Hpet/Hpet.aslc create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/INTELGFX.ASL create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/INTELISPDev2.ASL create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOGBDA.ASL create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOMOBF.ASL create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOSBCB.ASL create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOpRn.ASL create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IoTVirtualDevice.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/LPC_DEV.ASL create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/LpcB.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Lpit/Lpit.aslc create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Madt/Madt.h create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Madt/Madt30.aslc create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Mcfg/Mcfg.aslc create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PCI_DRC.ASL create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Pch.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchAudio.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchEhci.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchLpss.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchPcie.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchScc.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchSmb.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchXhci.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PciTree.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Platform.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/RTD3.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/THERMAL.ASL create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/UsbSbd.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Video.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Vlv.asl create mode 100644 Vlv2DeviceRefCodePkg/AcpiTablesPCAT/token.asl create mode 100644 Vlv2DeviceRefCodePkg/Include/Guid/Vlv2DeviceRefCodePkgTokenSpace.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Guid/PowerManagementAcpiTableStorage.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Ppi/VlvPolicy.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Protocol/PpmPlatformPolicy.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Types.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/PowerManagementAcpiTables.inf create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/ApCst.asl create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/ApIst.asl create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/ApTst.asl create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/Cpu0Cst.asl create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/Cpu0Ist.asl create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/Cpu0Tst.asl create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/CpuPm.asl create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/PlatformBaseAddresses.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/Capsule.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/PlatformMemoryRange.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/PlatformMemorySize.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/SmmAccess.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/VlvMmioPolicy.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/VlvPeiInit.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/VlvPolicy.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/IgdOpRegion.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/MemInfo.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/PlatformGopPolicy.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/VlvPlatformPolicy.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Valleyview.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/VlvAccess.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/VlvCommonDefinitions.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/PchInitVar.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/SataControllerGuid.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/SmbusArpMap.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/Vlv2Variable.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/IndustryStandard/CeAta.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/IndustryStandard/Mmc.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/IndustryStandard/SdCard.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Library/I2CLib.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Library/PchPlatformLib.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchAccess.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchCommonDefinitions.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsHda.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsLpss.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsPcie.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsPcu.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsRcrb.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsSata.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsScc.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsSmbus.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsSpi.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsUsb.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchInit.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchPeiInit.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchPlatformPolicy.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchUsbPolicy.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PeiBlockIo.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/Sdhc.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/SmbusPolicy.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/Spi.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/ActiveBios.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/ActiveBiosProtocol.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/DxePchPolicyUpdateProtocol.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/EmmcCardInfoProtocol.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/Gpio.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/HwWatchdogTimer.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/I2cBus.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchExtendedReset.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchInfo.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchPlatformPolicy.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchReset.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchS3Support.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SdHostIo.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SmbiosSlotPopulation.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SmmIchnDispatchEx.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SmmSmbus.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/Spi.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/TcoReset.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Rsci.h create mode 100644 Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/TianoApi.h create mode 100644 Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec create mode 100644 Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.c create mode 100644 Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.h create mode 100644 Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.inf create mode 100644 Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatformHooks.c create mode 100644 Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatformHooks.h create mode 100644 Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatformHooksLib.h create mode 100644 Vlv2TbltDevicePkg/AcpiPlatform/Osfr.h create mode 100644 Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.c create mode 100644 Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.h create mode 100644 Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf create mode 100644 Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdateStrings.uni create mode 100644 Vlv2TbltDevicePkg/BfmLib.exe create mode 100644 Vlv2TbltDevicePkg/BiosIdD.env create mode 100644 Vlv2TbltDevicePkg/BiosIdR.env create mode 100644 Vlv2TbltDevicePkg/BiosIdx64D.env create mode 100644 Vlv2TbltDevicePkg/BiosIdx64R.env create mode 100644 Vlv2TbltDevicePkg/BootScriptSaveDxe/BootScriptSaveDxe.inf create mode 100644 Vlv2TbltDevicePkg/BootScriptSaveDxe/InternalBootScriptSave.h create mode 100644 Vlv2TbltDevicePkg/BootScriptSaveDxe/ScriptSave.c create mode 100644 Vlv2TbltDevicePkg/Build_IFWI.bat create mode 100644 Vlv2TbltDevicePkg/Build_IFWI.sh create mode 100644 Vlv2TbltDevicePkg/FCE.exe create mode 100644 Vlv2TbltDevicePkg/FspAzaliaConfigData/AzaliaConfig.bin create mode 100644 Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.c create mode 100644 Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.inf create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/PeiFspHobProcessLibVlv2/FspHobProcessLibVlv2.c create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/PeiFspHobProcessLibVlv2/FspHobProcessLibVlv2.inf create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/FspPlatformSecLibVlv2.c create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/FspPlatformSecLibVlv2.inf create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/AsmSaveSecContext.asm create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/Fsp.inc create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/PeiCoreEntry.asm create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/SecEntry.asm create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/Stack.S create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/Stack.asm create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/PlatformInit.c create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SaveSecContext.c create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecGetPerformance.c create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecPlatformInformation.c create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecRamInitData.c create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecTempRamSupport.c create mode 100644 Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/UartInit.c create mode 100644 Vlv2TbltDevicePkg/FvInfoPei/FvInfoPei.c create mode 100644 Vlv2TbltDevicePkg/FvInfoPei/FvInfoPei.inf create mode 100644 Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbInfo.c create mode 100644 Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbRuntimeDxe.inf create mode 100644 Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.c create mode 100644 Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.h create mode 100644 Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbServiceDxe.c create mode 100644 Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbServiceSmm.c create mode 100644 Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmm.inf create mode 100644 Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmCommon.h create mode 100644 Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.c create mode 100644 Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.h create mode 100644 Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.inf create mode 100644 Vlv2TbltDevicePkg/GenBiosId create mode 100644 Vlv2TbltDevicePkg/GenBiosId.exe create mode 100644 Vlv2TbltDevicePkg/Include/AlertStandardFormatTable.h create mode 100644 Vlv2TbltDevicePkg/Include/ChipsetAccess.h create mode 100644 Vlv2TbltDevicePkg/Include/CommonIncludes.h create mode 100644 Vlv2TbltDevicePkg/Include/CpuType.h create mode 100644 Vlv2TbltDevicePkg/Include/FileHandleLib.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/AcpiTableStorage.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/AlertStandardFormat.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/BiosId.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/BoardFeatures.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/EfiVpdData.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/FirmwareId.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/HwWatchdogTimerHob.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/IdccData.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/ItkData.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/MemoryConfigData.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/OsSelection.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/PciLanInfo.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/PlatformCpuInfo.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/PlatformInfo.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/SensorInfoVariable.h create mode 100644 Vlv2TbltDevicePkg/Include/Guid/SetupVariable.h create mode 100644 Vlv2TbltDevicePkg/Include/Hpet.h create mode 100644 Vlv2TbltDevicePkg/Include/Library/BiosIdLib.h create mode 100644 Vlv2TbltDevicePkg/Include/Library/CpuIA32.h create mode 100644 Vlv2TbltDevicePkg/Include/Library/EfiRegTableLib.h create mode 100644 Vlv2TbltDevicePkg/Include/Library/Esrt.h create mode 100644 Vlv2TbltDevicePkg/Include/Library/Fd.h create mode 100644 Vlv2TbltDevicePkg/Include/Library/FlashDeviceLib.h create mode 100644 Vlv2TbltDevicePkg/Include/Library/I2cMmioConfigLib.h create mode 100644 Vlv2TbltDevicePkg/Include/Library/I2cPort_platform.h create mode 100644 Vlv2TbltDevicePkg/Include/Library/PlatformFsaLib.h create mode 100644 Vlv2TbltDevicePkg/Include/Library/PlatformFspLib.h create mode 100644 Vlv2TbltDevicePkg/Include/Library/SpiFlash.H create mode 100644 Vlv2TbltDevicePkg/Include/Library/StallSmmLib.h create mode 100644 Vlv2TbltDevicePkg/Include/Library/UsbDeviceModeLib.h create mode 100644 Vlv2TbltDevicePkg/Include/Mcfg.h create mode 100644 Vlv2TbltDevicePkg/Include/McfgTable.h create mode 100644 Vlv2TbltDevicePkg/Include/Platform.h create mode 100644 Vlv2TbltDevicePkg/Include/PlatformBootMode.h create mode 100644 Vlv2TbltDevicePkg/Include/PlatformDefinitions.h create mode 100644 Vlv2TbltDevicePkg/Include/Ppi/MfgMemoryTest.h create mode 100644 Vlv2TbltDevicePkg/Include/Ppi/Sha256Hash.h create mode 100644 Vlv2TbltDevicePkg/Include/Ppi/Speaker.h create mode 100644 Vlv2TbltDevicePkg/Include/Ppi/UsbController.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/CK505ClockPlatformInfo.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/EnhancedSpeedstep.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/GlobalNvsArea.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/HwWatchdogTimer.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/I2cAcpi.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/I2cBus.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/I2cBusMcg.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/I2cHostMcg.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/I2cMasterMcg.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/I2cSlave.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/LpcWpc83627Policy.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/LpcWpce791Policy.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/MmioDevice.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/Observable.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/PlatformGopPolicy.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/PlatformIdeInit.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/SetupMode.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/SmbiosSlotPopulation.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/Speaker.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/TcoReset.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/TpmMp.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/UsbPolicy.h create mode 100644 Vlv2TbltDevicePkg/Include/Protocol/VlvPlatformPolicy.h create mode 100644 Vlv2TbltDevicePkg/Include/SetupMode.h create mode 100644 Vlv2TbltDevicePkg/IntelGopDepex/IntelGopDriver.depex create mode 100644 Vlv2TbltDevicePkg/Library/BiosIdLib/BiosIdLib.c create mode 100644 Vlv2TbltDevicePkg/Library/BiosIdLib/BiosIdLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/CpuIA32Lib/CpuIA32Lib.inf create mode 100644 Vlv2TbltDevicePkg/Library/CpuIA32Lib/EfiCpuVersion.c create mode 100644 Vlv2TbltDevicePkg/Library/CpuIA32Lib/IA32/CpuIA32.S create mode 100644 Vlv2TbltDevicePkg/Library/CpuIA32Lib/IA32/CpuIA32.asm create mode 100644 Vlv2TbltDevicePkg/Library/CpuIA32Lib/IA32/CpuIA32.c create mode 100644 Vlv2TbltDevicePkg/Library/CpuIA32Lib/X64/Cpu.S create mode 100644 Vlv2TbltDevicePkg/Library/CpuIA32Lib/X64/Cpu.asm create mode 100644 Vlv2TbltDevicePkg/Library/EfiRegTableLib/EfiRegTableLib.c create mode 100644 Vlv2TbltDevicePkg/Library/EfiRegTableLib/EfiRegTableLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h create mode 100644 Vlv2TbltDevicePkg/Library/I2CLib/I2CLib.c create mode 100644 Vlv2TbltDevicePkg/Library/I2CLib/I2CLibNull.inf create mode 100644 Vlv2TbltDevicePkg/Library/IntelPchAcpiTimerLib/CommonHeader.h create mode 100644 Vlv2TbltDevicePkg/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.c create mode 100644 Vlv2TbltDevicePkg/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.c create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.h create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardGpios/BoardGpios.c create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardGpios/BoardGpios.h create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardJumpers/BoardJumpers.c create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardJumpers/BoardJumpers.h create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardOemIds/BoardOemIds.c create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardOemIds/BoardOemIds.h create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardSsidSvid/BoardSsidSvid.c create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardSsidSvid/BoardSsidSvid.h create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/MultiPlatformLib.c create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/MultiPlatformLib.h create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/MultiPlatformLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/MultiPlatformLib/PlatformInfoHob.c create mode 100644 Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLibrary.c create mode 100644 Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLibrary.h create mode 100644 Vlv2TbltDevicePkg/Library/PchSmmLib/CommonHeader.h create mode 100644 Vlv2TbltDevicePkg/Library/PchSmmLib/PchSmmLib.c create mode 100644 Vlv2TbltDevicePkg/Library/PchSmmLib/PchSmmLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c create mode 100644 Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.h create mode 100644 Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformData.c create mode 100644 Vlv2TbltDevicePkg/Library/PlatformCmosLib/PlatformCmosLib.c create mode 100644 Vlv2TbltDevicePkg/Library/PlatformCmosLib/PlatformCmosLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/PlatformFspLib/PlatformFspLib.c create mode 100644 Vlv2TbltDevicePkg/Library/PlatformFspLib/PlatformFspLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/ResetSystemLib/ResetSystemLib.c create mode 100644 Vlv2TbltDevicePkg/Library/ResetSystemLib/ResetSystemLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/SerialPortLib/PlatformSerialPortLib.h create mode 100644 Vlv2TbltDevicePkg/Library/SerialPortLib/SerialPortLib.c create mode 100644 Vlv2TbltDevicePkg/Library/SerialPortLib/SerialPortLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/SerialPortLib/SioInit.c create mode 100644 Vlv2TbltDevicePkg/Library/SerialPortLib/SioInit.h create mode 100644 Vlv2TbltDevicePkg/Library/SmbusLib/CommonHeader.h create mode 100644 Vlv2TbltDevicePkg/Library/SmbusLib/SmbusLib.c create mode 100644 Vlv2TbltDevicePkg/Library/SmbusLib/SmbusLib.inf create mode 100644 Vlv2TbltDevicePkg/Library/StallSmmLib/StallSmm.c create mode 100644 Vlv2TbltDevicePkg/Library/StallSmmLib/StallSmmLib.inf create mode 100644 Vlv2TbltDevicePkg/Logo/Logo.bmp create mode 100644 Vlv2TbltDevicePkg/Metronome/LegacyMetronome.c create mode 100644 Vlv2TbltDevicePkg/Metronome/LegacyMetronome.h create mode 100644 Vlv2TbltDevicePkg/Metronome/Metronome.inf create mode 100644 Vlv2TbltDevicePkg/MonoStatusCode/EfiStatusCode.h create mode 100644 Vlv2TbltDevicePkg/MonoStatusCode/MonoStatusCode.c create mode 100644 Vlv2TbltDevicePkg/MonoStatusCode/MonoStatusCode.h create mode 100644 Vlv2TbltDevicePkg/MonoStatusCode/MonoStatusCode.inf create mode 100644 Vlv2TbltDevicePkg/MonoStatusCode/PeiPostCode.c create mode 100644 Vlv2TbltDevicePkg/MonoStatusCode/PlatformStatusCode.c create mode 100644 Vlv2TbltDevicePkg/MonoStatusCode/PlatformStatusCode.h create mode 100644 Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c create mode 100644 Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c create mode 100644 Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c create mode 100644 Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c create mode 100644 Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c create mode 100644 Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf create mode 100644 Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsStrings.uni create mode 100644 Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h create mode 100644 Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c create mode 100644 Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/String.c create mode 100644 Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/String.h create mode 100644 Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ComponentName.c create mode 100644 Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c create mode 100644 Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h create mode 100644 Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf create mode 100644 Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c create mode 100644 Vlv2TbltDevicePkg/PciPlatform/BoardPciPlatform.c create mode 100644 Vlv2TbltDevicePkg/PciPlatform/PciPlatform.c create mode 100644 Vlv2TbltDevicePkg/PciPlatform/PciPlatform.h create mode 100644 Vlv2TbltDevicePkg/PciPlatform/PciPlatform.inf create mode 100644 Vlv2TbltDevicePkg/PlatformCpuInfoDxe/PlatformCpuInfoDxe.c create mode 100644 Vlv2TbltDevicePkg/PlatformCpuInfoDxe/PlatformCpuInfoDxe.h create mode 100644 Vlv2TbltDevicePkg/PlatformCpuInfoDxe/PlatformCpuInfoDxe.inf create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/AzaliaVerbTable.h create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/BoardId.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/BoardIdDecode.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/BoardIdDecode.h create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/ClockControl.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/Configuration.h create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/ExI.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/IchPlatformPolicy.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/IchRegTable.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/IchTcoReset.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/IdccInfo.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/LegacySpeaker.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/LegacySpeaker.h create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/Observable/Observable.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/Observable/Observable.h create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/PciBus.h create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/PciDevice.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/Platform.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/PlatformDxe.h create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/PlatformDxe.inf create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/SensorVar.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/SioPlatformPolicy.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/SlotConfig.c create mode 100644 Vlv2TbltDevicePkg/PlatformDxe/SlotConfig.h create mode 100644 Vlv2TbltDevicePkg/PlatformGopPolicy/PlatformGopPolicy.c create mode 100644 Vlv2TbltDevicePkg/PlatformGopPolicy/PlatformGopPolicy.inf create mode 100644 Vlv2TbltDevicePkg/PlatformInfoDxe/PlatformInfoDxe.c create mode 100644 Vlv2TbltDevicePkg/PlatformInfoDxe/PlatformInfoDxe.h create mode 100644 Vlv2TbltDevicePkg/PlatformInfoDxe/PlatformInfoDxe.inf create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/BootMode.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/CpuInitPeim.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/Dimm.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/FlashMap.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/LegacySpeaker.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/LegacySpeaker.h create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/MchInit.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/MemoryCallback.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/MemoryPeim.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/PchInitPeim.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/PlatformEarlyInit.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/PlatformEarlyInit.h create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/PlatformInfoInit.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/PlatformInitPei.inf create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/PlatformSsaInitPeim.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/Recovery.c create mode 100644 Vlv2TbltDevicePkg/PlatformInitPei/Stall.c create mode 100644 Vlv2TbltDevicePkg/PlatformPei/BootMode.c create mode 100644 Vlv2TbltDevicePkg/PlatformPei/CommonHeader.h create mode 100644 Vlv2TbltDevicePkg/PlatformPei/MemoryCallback.c create mode 100644 Vlv2TbltDevicePkg/PlatformPei/Platform.c create mode 100644 Vlv2TbltDevicePkg/PlatformPei/Platform.h create mode 100644 Vlv2TbltDevicePkg/PlatformPei/PlatformPei.inf create mode 100644 Vlv2TbltDevicePkg/PlatformPei/Stall.c create mode 100644 Vlv2TbltDevicePkg/PlatformPkg.dec create mode 100644 Vlv2TbltDevicePkg/PlatformPkg.fdf create mode 100644 Vlv2TbltDevicePkg/PlatformPkgConfig.dsc create mode 100644 Vlv2TbltDevicePkg/PlatformPkgGcc.fdf create mode 100644 Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc create mode 100644 Vlv2TbltDevicePkg/PlatformPkgIA32.dsc create mode 100644 Vlv2TbltDevicePkg/PlatformPkgX64.dsc create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/Boot.vfi create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/Configuration.h create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/DebugConfig.vfi create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/FwVersionStrings.uni create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/Main.vfi create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/PlatformSetupDxe.c create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/PlatformSetupDxe.h create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/PlatformSetupDxe.inf create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/Security.vfi create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/SetupFunctions.c create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/SetupInfoRecords.c create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/SouthClusterConfig.vfi create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/SystemComponent.vfi create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/Thermal.vfi create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/UnCore.vfi create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/UqiList.uni create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/Vfr.vfr create mode 100644 Vlv2TbltDevicePkg/PlatformSetupDxe/VfrStrings.uni create mode 100644 Vlv2TbltDevicePkg/PlatformSmm/Platform.c create mode 100644 Vlv2TbltDevicePkg/PlatformSmm/PlatformSmm.inf create mode 100644 Vlv2TbltDevicePkg/PlatformSmm/S3Save.c create mode 100644 Vlv2TbltDevicePkg/PlatformSmm/SmmPlatform.h create mode 100644 Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.c create mode 100644 Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.h create mode 100644 Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.c create mode 100644 Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.h create mode 100644 Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.inf create mode 100644 Vlv2TbltDevicePkg/SaveMemoryConfig/SaveMemoryConfig.c create mode 100644 Vlv2TbltDevicePkg/SaveMemoryConfig/SaveMemoryConfig.h create mode 100644 Vlv2TbltDevicePkg/SaveMemoryConfig/SaveMemoryConfig.inf create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/CommonHeader.h create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBaseBoardManufacturer.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBaseBoardManufacturerData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBaseBoardManufacturerFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBiosVendor.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBiosVendorData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBiosVendorFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBootInformationData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBootInformationFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscChassisManufacturer.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscChassisManufacturerData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscChassisManufacturerFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscMemoryDevice.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscMemoryDeviceData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscMemoryDeviceFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscNumberOfInstallableLanguagesData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscNumberOfInstallableLanguagesFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemString.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemStringData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemStringFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x90.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x90Data.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x90Function.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x94.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x94Data.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x94Function.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOnboardDevice.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOnboardDeviceData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOnboardDeviceFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPhysicalArray.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPhysicalArrayData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPhysicalArrayFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPortInternalConnectorDesignator.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPortInternalConnectorDesignatorData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPortInternalConnectorDesignatorFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorCache.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorCacheData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorCacheFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformation.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscResetCapabilitiesData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscResetCapabilitiesFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriver.h create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriver.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriverDataTable.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriverEntryPoint.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemLanguageString.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemLanguageStringData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemLanguageStringFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemManufacturer.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemManufacturerData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemManufacturerFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemOptionString.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemOptionStringData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemOptionStringFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemSlotDesignation.uni create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemSlotDesignationData.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemSlotDesignationFunction.c create mode 100644 Vlv2TbltDevicePkg/SmBiosMiscDxe/SmBiosMiscDxe.inf create mode 100644 Vlv2TbltDevicePkg/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.c create mode 100644 Vlv2TbltDevicePkg/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf create mode 100644 Vlv2TbltDevicePkg/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.c create mode 100644 Vlv2TbltDevicePkg/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.inf create mode 100644 Vlv2TbltDevicePkg/Stitch/Gcc/NvStorageFtwSpare.bin create mode 100644 Vlv2TbltDevicePkg/Stitch/Gcc/NvStorageFtwWorking.bin create mode 100644 Vlv2TbltDevicePkg/Stitch/Gcc/NvStorageVariable.bin create mode 100644 Vlv2TbltDevicePkg/Stitch/IFWIHeader/IFWI_HEADER.bin create mode 100644 Vlv2TbltDevicePkg/Stitch/IFWIHeader/Vacant.bin create mode 100644 Vlv2TbltDevicePkg/Stitch/IFWIStitch.bat create mode 100644 Vlv2TbltDevicePkg/Stitch/MNW2_Stitch_Config.txt create mode 100644 Vlv2TbltDevicePkg/UiApp/FrontPage.c create mode 100644 Vlv2TbltDevicePkg/UiApp/UiApp.inf create mode 100644 Vlv2TbltDevicePkg/VlvPlatformInitDxe/IgdOpRegion.c create mode 100644 Vlv2TbltDevicePkg/VlvPlatformInitDxe/IgdOpRegion.h create mode 100644 Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInit.c create mode 100644 Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInit.h create mode 100644 Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInitDxe.inf create mode 100644 Vlv2TbltDevicePkg/Wpce791/LpcDriver.c create mode 100644 Vlv2TbltDevicePkg/Wpce791/LpcDriver.h create mode 100644 Vlv2TbltDevicePkg/Wpce791/LpcIsaAcpi.c create mode 100644 Vlv2TbltDevicePkg/Wpce791/LpcIsaAcpi.h create mode 100644 Vlv2TbltDevicePkg/Wpce791/LpcSio.c create mode 100644 Vlv2TbltDevicePkg/Wpce791/LpcSio.h create mode 100644 Vlv2TbltDevicePkg/Wpce791/Wpce791.inf create mode 100644 Vlv2TbltDevicePkg/bldX64.bat create mode 100644 Vlv2TbltDevicePkg/bld_vlv.bat create mode 100644 Vlv2TbltDevicePkg/bld_vlv.sh create mode 100644 Vlv2TbltDevicePkg/cln.sh diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/98_LINK.ASL b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/98_LINK.ASL new file mode 100644 index 0000000000..ac13f36690 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/98_LINK.ASL @@ -0,0 +1,623 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + + + +// Use this information when determining the Possible IRQs that can be +// used in a given system. +// +// The following IRQs are always in use by legacy devices: +// 0 = System Timer +// 2 = 8259 PIC +// 8 = RTC +// 9 = SCI Interrupt (It may be used, we choose not to) +// 13 = Co-processor Error +// +// The following may be in use by legacy devices: +// 1 = If using PS/2 Keyboard +// 3 = If COMx Port Enabled and IRQ = 3 +// 4 = If COMx Port Enabled and IRQ = 4 +// 5 = If LPT Port Enabled and IRQ = 5 +// 6 = If FDC Enabled +// 7 = If LPT Port Enabled and IRQ = 7 +// 12 = If using PS/2 Mouse +// 14 = Primary IDE (If populated and in Compatibility Mode) +// 15 = Secondary IDE (If populated and in Compatibility Mode) +// +// The following will never be in use by legacy devices: +// 10 = Assign to PARC, PCRC, PERC, PGRC +// 11 = Assign to PBRC, PDRC, PFRC, PHRC + +Device(LNKA) // PARC Routing Resource +{ + Name(_HID,EISAID("PNP0C0F")) // PCI Interrupt Link Device + + Name(_UID,1) // Unique to other Link Devices + + // Disable the PCI IRQ. + + Method(_DIS,0,Serialized) + { + Or(PARC,0x80,PARC) + } + + // Possible IRQ Resource Setting. + + Method (_PRS, 0, Serialized) + { + return (PRSA) + } + + // Current IRQ Resource Setting. + + Method(_CRS,0,Serialized) + { + Name(RTLA,ResourceTemplate() + { + IRQ(Level,ActiveLow,Shared) {} + }) + + // Point to specific byte. + + CreateWordField(RTLA,1,IRQ0) + + // Zero out IRQ mask bits 0-15 + + Store(Zero,IRQ0) + + ShiftLeft(1,And(PARC,0x0F),IRQ0) + + Return(RTLA) + } + + // Set IRQ Resource Setting. + + Method(_SRS,1,Serialized) + { + // Point to the specific byte passed in + + CreateWordField(Arg0,1,IRQ0) + + // Determine the IRQ bit to set and store it + + FindSetRightBit(IRQ0,Local0) + Decrement(Local0) + Store(Local0,PARC) + } + + // PCI IRQ Status. + + Method(_STA,0,Serialized) + { + If(And(PARC,0x80)) + { + Return(0x0009) + } + Else + { + Return(0x000B) + } + } +} + +Device(LNKB) // PBRC Routing Resource +{ + Name(_HID,EISAID("PNP0C0F")) + + Name(_UID,2) + + // Disable the PCI IRQ. + + Method(_DIS,0,Serialized) + { + Or(PBRC,0x80,PBRC) + } + + // Possible IRQ Resource Setting. + + Method (_PRS, 0, Serialized) + { + return (PRSB) + } + + // Current IRQ Resource Setting. + + Method(_CRS,0,Serialized) + { + Name(RTLB,ResourceTemplate() + { + IRQ(Level,ActiveLow,Shared) {} + }) + + // Point to specific byte. + + CreateWordField(RTLB,1,IRQ0) + + // Zero out IRQ mask bits 0-15 + + Store(Zero,IRQ0) + + ShiftLeft(1,And(PBRC,0x0F),IRQ0) + + Return(RTLB) + } + + // Set IRQ Resource Setting. + + Method(_SRS,1,Serialized) + { + // Point to the specific byte passed in. + + CreateWordField(Arg0,1,IRQ0) + + // Determine the IRQ bit to set and store it, + + FindSetRightBit(IRQ0,Local0) + Decrement(Local0) + Store(Local0,PBRC) + } + + // PCI IRQ Status. + + Method(_STA,0,Serialized) + { + If(And(PBRC,0x80)) + { + Return(0x0009) + } + Else + { + Return(0x000B) + } + } +} + +Device(LNKC) // PCRC Routing Resource +{ + Name(_HID,EISAID("PNP0C0F")) + + Name(_UID,3) + + // Disable the PCI IRQ. + + Method(_DIS,0,Serialized) + { + Or(PCRC,0x80,PCRC) + } + + // Possible IRQ Resource Setting. + + Method (_PRS, 0, Serialized) + { + return (PRSC) + } + + // Current IRQ Resource Setting. + + Method(_CRS,0,Serialized) + { + Name(RTLC,ResourceTemplate() + { + IRQ(Level,ActiveLow,Shared) {} + }) + + // Point to specific byte. + + CreateWordField(RTLC,1,IRQ0) + + // Zero out IRQ mask bits 0-15 + + Store(Zero,IRQ0) + + ShiftLeft(1,And(PCRC,0x0F),IRQ0) + + Return(RTLC) + } + + // Set IRQ Resource Setting. + + Method(_SRS,1,Serialized) + { + // Point to the specific byte passed in. + + CreateWordField(Arg0,1,IRQ0) + + // Determine the IRQ bit to set and store it, + + FindSetRightBit(IRQ0,Local0) + Decrement(Local0) + Store(Local0,PCRC) + } + + // PCI IRQ Status. + + Method(_STA,0,Serialized) + { + If(And(PCRC,0x80)) + { + Return(0x0009) + } + Else + { + Return(0x000B) + } + } +} + +Device(LNKD) // PDRC Routing Resource +{ + Name(_HID,EISAID("PNP0C0F")) + + Name(_UID,4) + + // Disable the PCI IRQ. + + Method(_DIS,0,Serialized) + { + Or(PDRC,0x80,PDRC) + } + + // Possible IRQ Resource Setting. + + Method (_PRS, 0, Serialized) + { + return (PRSD) + } + + // Current IRQ Resource Setting. + + Method(_CRS,0,Serialized) + { + Name(RTLD,ResourceTemplate() + { + IRQ(Level,ActiveLow,Shared) {} + }) + + // Point to specific byte. + + CreateWordField(RTLD,1,IRQ0) + + // Zero out IRQ mask bits 0-15 + + Store(Zero,IRQ0) + + ShiftLeft(1,And(PDRC,0x0F),IRQ0) + + Return(RTLD) + } + + // Set IRQ Resource Setting. + + Method(_SRS,1,Serialized) + { + // Point to the specific byte passed in. + + CreateWordField(Arg0,1,IRQ0) + + // Determine the IRQ bit to set and store it, + + FindSetRightBit(IRQ0,Local0) + Decrement(Local0) + Store(Local0,PDRC) + } + + // PCI IRQ Status. + + Method(_STA,0,Serialized) + { + If(And(PDRC,0x80)) + { + Return(0x0009) + } + Else + { + Return(0x000B) + } + } +} + +Device(LNKE) // PERC Routing Resource +{ + Name(_HID,EISAID("PNP0C0F")) + + Name(_UID,5) + + // Disable the PCI IRQ. + + Method(_DIS,0,Serialized) + { + Or(PERC,0x80,PERC) + } + + // Possible IRQ Resource Setting. + + Method (_PRS, 0, Serialized) + { + return (PRSE) + } + + // Current IRQ Resource Setting. + + Method(_CRS,0,Serialized) + { + Name(RTLE,ResourceTemplate() + { + IRQ(Level,ActiveLow,Shared) {} + }) + + // Point to specific byte. + + CreateWordField(RTLE,1,IRQ0) + + // Zero out IRQ mask bits 0-15 + + Store(Zero,IRQ0) + + ShiftLeft(1,And(PERC,0x0F),IRQ0) + + Return(RTLE) + } + + // Set IRQ Resource Setting. + + Method(_SRS,1,Serialized) + { + // Point to the specific byte passed in + + CreateWordField(Arg0,1,IRQ0) + + // Determine the IRQ bit to set and store it + + FindSetRightBit(IRQ0,Local0) + Decrement(Local0) + Store(Local0,PERC) + } + + // PCI IRQ Status. + + Method(_STA,0,Serialized) + { + If(And(PERC,0x80)) + { + Return(0x0009) + } + Else + { + Return(0x000B) + } + } +} + +Device(LNKF) // PFRC Routing Resource +{ + Name(_HID,EISAID("PNP0C0F")) + + Name(_UID,6) + + // Disable the PCI IRQ. + + Method(_DIS,0,Serialized) + { + Or(PFRC,0x80,PFRC) + } + + // Possible IRQ Resource Setting. + + Method (_PRS, 0, Serialized) + { + return (PRSF) + } + + // Current IRQ Resource Setting. + + Method(_CRS,0,Serialized) + { + Name(RTLF,ResourceTemplate() + { + IRQ(Level,ActiveLow,Shared) {} + }) + + // Point to specific byte. + + CreateWordField(RTLF,1,IRQ0) + + // Zero out IRQ mask bits 0-15 + + Store(Zero,IRQ0) + + ShiftLeft(1,And(PFRC,0x0F),IRQ0) + + Return(RTLF) + } + + // Set IRQ Resource Setting. + + Method(_SRS,1,Serialized) + { + // Point to the specific byte passed in. + + CreateWordField(Arg0,1,IRQ0) + + // Determine the IRQ bit to set and store it, + + FindSetRightBit(IRQ0,Local0) + Decrement(Local0) + Store(Local0,PFRC) + } + + // PCI IRQ Status. + + Method(_STA,0,Serialized) + { + If(And(PFRC,0x80)) + { + Return(0x0009) + } + Else + { + Return(0x000B) + } + } +} + +Device(LNKG) // PGRC Routing Resource +{ + Name(_HID,EISAID("PNP0C0F")) + + Name(_UID,7) + + // Disable the PCI IRQ. + + Method(_DIS,0,Serialized) + { + Or(PGRC,0x80,PGRC) + } + + // Possible IRQ Resource Setting. + + Method (_PRS, 0, Serialized) + { + return (PRSG) + } + + // Current IRQ Resource Setting. + + Method(_CRS,0,Serialized) + { + Name(RTLG,ResourceTemplate() + { + IRQ(Level,ActiveLow,Shared) {} + }) + + // Point to specific byte. + + CreateWordField(RTLG,1,IRQ0) + + // Zero out IRQ mask bits 0-15 + + Store(Zero,IRQ0) + + ShiftLeft(1,And(PGRC,0x0F),IRQ0) + + Return(RTLG) + } + + // Set IRQ Resource Setting. + + Method(_SRS,1,Serialized) + { + // Point to the specific byte passed in. + + CreateWordField(Arg0,1,IRQ0) + + // Determine the IRQ bit to set and store it, + + FindSetRightBit(IRQ0,Local0) + Decrement(Local0) + Store(Local0,PGRC) + } + + // PCI IRQ Status. + + Method(_STA,0,Serialized) + { + If(And(PGRC,0x80)) + { + Return(0x0009) + } + Else + { + Return(0x000B) + } + } +} + +Device(LNKH) // PHRC Routing Resource +{ + Name(_HID,EISAID("PNP0C0F")) + + Name(_UID,8) + + // Disable the PCI IRQ. + + Method(_DIS,0,Serialized) + { + Or(PHRC,0x80,PHRC) + } + + // Possible IRQ Resource Setting. + + Method (_PRS, 0, Serialized) + { + return (PRSH) + } + + // Current IRQ Resource Setting. + + Method(_CRS,0,Serialized) + { + Name(RTLH,ResourceTemplate() + { + IRQ(Level,ActiveLow,Shared) {} + }) + + // Point to specific byte. + + CreateWordField(RTLH,1,IRQ0) + + // Zero out IRQ mask bits 0-15 + + Store(Zero,IRQ0) + + ShiftLeft(1,And(PHRC,0x0F),IRQ0) + + Return(RTLH) + } + + // Set IRQ Resource Setting. + + Method(_SRS,1,Serialized) + { + // Point to the specific byte passed in. + + CreateWordField(Arg0,1,IRQ0) + + // Determine the IRQ bit to set and store it, + + FindSetRightBit(IRQ0,Local0) + Decrement(Local0) + Store(Local0,PHRC) + } + + // PCI IRQ Status. + + Method(_STA,0,Serialized) + { + If(And(PHRC,0x80)) + { + Return(0x0009) + } + Else + { + Return(0x000B) + } + } +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/AcpiTablePlatform.h b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/AcpiTablePlatform.h new file mode 100644 index 0000000000..1f81d2586c --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/AcpiTablePlatform.h @@ -0,0 +1,76 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + AcpiTablePlatform.h + + +Abstract: File contains platform specific ACPI defines for use in ACPI tables + + +--*/ +#ifndef _Platform_h_INCLUDED_ +#define _Platform_h_INCLUDED_ + +#ifdef ECP_FLAG +#include "EdkIIGlueDxe.h" +#endif +#include +// +// ACPI table information used to initialize tables. +// +#define EFI_ACPI_OEM_ID 'O','E','M','I','D',' ' // OEMID 6 bytes long +#define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('O','E','M','T','A','B','L','E') // OEM table id 8 bytes long +#define EFI_ACPI_OEM_REVISION 0x00000005 +#define EFI_ACPI_CREATOR_ID SIGNATURE_32('C','R','E','A') +#define EFI_ACPI_CREATOR_REVISION 0x0100000D +#define INT_MODEL 0x01 +#define PM_PROFILE EFI_ACPI_4_0_PM_PROFILE_MOBILE +#define SCI_INT_VECTOR 0x0009 +#define SMI_CMD_IO_PORT 0x000000B2 +#define ACPI_ENABLE 0x0A0 +#define ACPI_DISABLE 0x0A1 +#define S4BIOS_REQ 0x00 +#define PSTATE_CNT 0x00 +#define PM1a_EVT_BLK 0x00000400 +#define PM1b_EVT_BLK 0x00000000 +#define PM1a_CNT_BLK 0x00000404 +#define PM1b_CNT_BLK 0x00000000 +#define PM2_CNT_BLK 0x00000450 +#define PM_TMR_BLK 0x00000408 +#define GPE0_BLK 0x00000420 +#define GPE1_BLK 0x00000000 +#define PM1_EVT_LEN 0x04 +#define PM1_CNT_LEN 0x02 +#define PM2_CNT_LEN 0x01 +#define PM_TM_LEN 0x04 +#define GPE0_BLK_LEN 0x10 +#define GPE1_BLK_LEN 0x00 +#define GPE1_BASE 0x00 +#define CST_CNT 0x00 +#define P_LVL2_LAT 0x0064 +#define P_LVL3_LAT 0x01F4 +#define FLUSH_SIZE 0x0400 +#define FLUSH_STRIDE 0x0010 +#define DUTY_OFFSET 0x01 +#define DUTY_WIDTH 0x03 +#define DAY_ALRM 0x0D +#define MON_ALRM 0x00 +#define CENTURY 0x32 +#define FLAG ( EFI_ACPI_4_0_WBINVD | EFI_ACPI_4_0_SLP_BUTTON | EFI_ACPI_4_0_RESET_REG_SUP | EFI_ACPI_4_0_RTC_S4) +#define IAPC_BOOT_ARCH ( EFI_ACPI_4_0_VGA_NOT_PRESENT | EFI_ACPI_4_0_8042 | EFI_ACPI_4_0_LEGACY_DEVICES) +#define RESERVED 0x00 + +#endif diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/AcpiTables.inf b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/AcpiTables.inf new file mode 100644 index 0000000000..c857ab8c9a --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/AcpiTables.inf @@ -0,0 +1,44 @@ +## @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) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +## + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiTables + FILE_GUID = 7E374E25-8E01-4FEE-87F2-390C23C606CD + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + +[sources.common] + DSDT.ASL + Facs/Facs.aslc + Facp/Facp.aslc + Madt/Madt30.aslc + Mcfg/Mcfg.aslc + Hpet/Hpet.aslc + Lpit/Lpit.aslc + + +[Packages] + MdePkg/MdePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/CPU.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/CPU.asl new file mode 100644 index 0000000000..9092ff87cc --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/CPU.asl @@ -0,0 +1,55 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + + + +// NOTE: The _PDC Implementation is out of the scope of this +// reference code. Please see the latest Hyper-Threading Technology +// Reference Code for complete implementation details. + +Scope(\_PR) +{ + Processor(CPU0, // Unique name for Processor 0. + 1, // Unique ID for Processor 0. + 0x00, // CPU0 ACPI P_BLK address = ACPIBASE + 10h. + 0) // CPU0 P_BLK length = 6 bytes. + {} + + Processor(CPU1, // Unique name for Processor 1. + 2, // Unique ID for Processor 1. + 0x00, + 0) // CPU1 P_BLK length = 6 bytes. + {} + + Processor(CPU2, // Unique name for Processor 2. + 3, // Unique ID for Processor 2. + 0x00, + 0) // CPU2 P_BLK length = 6 bytes. + {} + + Processor(CPU3, // Unique name for Processor 3. + 4, // Unique ID for Processor 3. + 0x00, + 0) // CPU3 P_BLK length = 6 bytes. + {} +} // End _PR + + diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/DSDT.ASL b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/DSDT.ASL new file mode 100644 index 0000000000..56ed3372da --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/DSDT.ASL @@ -0,0 +1,81 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Sandy Bridge *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + +DefinitionBlock ( + "DSDT.aml", + "DSDT", + 0x02, // DSDT revision. + "OEMID", // OEM ID (6 byte string) + "VLV-SOC", // OEM table ID (8 byte string) + 0x0 // OEM version of DSDT table (4 byte Integer) +) + +// BEGIN OF ASL SCOPE +{ + External(MDBG, MethodObj) + + Method(ADBG, 1, Serialized) + { + + If(CondRefOf(MDBG)) //check if SSDT is loaded + { + Return(MDBG(Arg0)) + } + + Return(0) + } + + +// Miscellaneous services enabled in Project + include ("token.asl") + include ("GloblNvs.asl") + include ("PciTree.asl") + include ("Pch.asl") + include ("Vlv.asl") + include ("CPU.asl") + include ("Platform.asl") + include ("THERMAL.ASL") + include ("PCI_DRC.ASL") + include ("Video.asl") + include ("Gpe.asl") + include ("IoTVirtualDevice.asl") + + // Sleep states supported by Chipset/Board. + // SSx - BIOS setup controlled enabled _Sx Sleep state status + // Values to be written to SLP_TYPE register are provided by SBACPI.SDL (South Bridge ACPI ModulePart) + + Name(\_S0, Package(4) {0x0,0x0,0,0}) // mandatory System state + Name(\_S1, Package(4) {0x1,0x0,0,0}) + Name(\_S3, Package(4) {0x5,0x0,0,0}) + Name(\_S4, Package(4) {0x6,0x0,0,0}) + Name(\_S5, Package(4) {0x7,0x0,0,0}) // mandatory System state + + Method(PTS, 1) // METHOD CALLED FROM _PTS PRIOR TO ENTER ANY SLEEP STATE + { + If(Arg0) // entering any sleep state + { + } + } + Method(WAK, 1) // METHOD CALLED FROM _WAK RIGHT AFTER WAKE UP + { + } + +}// End of ASL File diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Facp/Facp.aslc b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Facp/Facp.aslc new file mode 100644 index 0000000000..c9319d53ba --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Facp/Facp.aslc @@ -0,0 +1,194 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Facp.c + + +Abstract: The fixed ACPI description Table (FADT) Structure + + +--*/ +#ifdef ECP_FLAG +#include "EDKIIGlueDxe.h" +#else +#include +#endif +#include +#include "AcpiTablePlatform.h" + +EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE FACP = { + { + EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, + sizeof (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE), + EFI_ACPI_5_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 (ignored in 2k and later, must be 0 for 98) + PM_PROFILE, // Preferred PM Profile + 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 + PSTATE_CNT, // PState control + PM1a_EVT_BLK, // Port address of Power Mgt 1a Event Reg Blk + PM1b_EVT_BLK, // Port address of Power Mgt 1b Event Reg Blk + PM1a_CNT_BLK, // Port address of Power Mgt 1a Ctrl Reg Blk + PM1b_CNT_BLK, // Port address of Power Mgt 1b Ctrl Reg Blk + PM2_CNT_BLK, // Port address of Power Mgt 2 Ctrl Reg Blk + PM_TMR_BLK, // Port address of Power Mgt Timer Ctrl Reg Blk + GPE0_BLK, // Port addr of General Purpose Event 0 Reg Blk + GPE1_BLK, // 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 + CST_CNT, // _CST support + 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-PCI Boot Architecture Flag + RESERVED, // reserved + FLAG, + { + EFI_ACPI_5_0_SYSTEM_IO, + 8, + 0, + 0, + 0xCF9 + }, + 0x06, // Hardware reset value + 0, 0, 0, // Reserved + 0, // XFirmwareCtrl + 0, // XDsdt + // + // X_PM1a Event Register Block + // + EFI_ACPI_5_0_SYSTEM_IO, + 0x20, + 0x00, + EFI_ACPI_3_0_DWORD, + PM1a_EVT_BLK, + + // + // X_PM1b Event Register Block + // + EFI_ACPI_5_0_SYSTEM_IO, + 0x00, + 0x00, + EFI_ACPI_RESERVED_BYTE, + PM1b_EVT_BLK, + + // + // X_PM1a Control Register Block + // + EFI_ACPI_5_0_SYSTEM_IO, + 0x10, + 0x00, + EFI_ACPI_3_0_WORD, + PM1a_CNT_BLK, + + // + // X_PM1b Control Register Block + // + EFI_ACPI_5_0_SYSTEM_IO, + 0x00, + 0x00, + EFI_ACPI_RESERVED_BYTE, + PM1b_CNT_BLK, + + // + // X_PM2 Control Register Block + // + EFI_ACPI_5_0_SYSTEM_IO, + 0x08, + 0x00, + EFI_ACPI_3_0_BYTE, + PM2_CNT_BLK, + + // + // X_PM Timer Control Register Block + // + EFI_ACPI_5_0_SYSTEM_IO, + 0x20, + 0x00, + EFI_ACPI_3_0_DWORD, + PM_TMR_BLK, + + // + // X_General Purpose Event 0 Register Block + // + EFI_ACPI_5_0_SYSTEM_IO, + 0x80, + 0x00, + EFI_ACPI_RESERVED_BYTE, + GPE0_BLK, + + // + // X_General Purpose Event 1 Register Block + // + EFI_ACPI_5_0_SYSTEM_IO, + 0x00, + 0x00, + EFI_ACPI_RESERVED_BYTE, + GPE1_BLK, + + // + // Sleep Control Register Block + // + EFI_ACPI_5_0_SYSTEM_IO, + 0x08, + 0x00, + EFI_ACPI_RESERVED_BYTE, + 0, + + // + // Sleep Status Register Block + // + EFI_ACPI_5_0_SYSTEM_IO, + 0x08, + 0x00, + EFI_ACPI_RESERVED_BYTE, + 0, +}; + +VOID* +ReferenceAcpiTable ( + VOID + ) +{ + // + // Reference the table being generated to prevent the optimizer from + // removing the data structure from the executable + // + return (VOID*)&FACP; +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Facs/Facs.aslc b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Facs/Facs.aslc new file mode 100644 index 0000000000..45050f0d3e --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Facs/Facs.aslc @@ -0,0 +1,90 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Ea815acpiFACS.c + + +Abstract: + + This file contains the FACS structure definition. + +--*/ + +// +// Statements that include other files +// +#ifdef ECP_FLAG +#include "EDKIIGlueDxe.h" +#else +#include +#endif +#include +#include "AcpiTablePlatform.h" + +EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE FACS = { + EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE, + sizeof (EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE), + + // + // Hardware Signature will be updated at runtime + // + 0x00000000, //HardwareSignature + 0x00000000, //FirmwareWakingVector + 0x00000000, //GlobalLock + 0x00000000, //Flags + 0x0000000000000000, //XFirmwareWakingVector + EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION, + EFI_ACPI_RESERVED_BYTE, //Reserved0[3] + EFI_ACPI_RESERVED_BYTE, + EFI_ACPI_RESERVED_BYTE, + 0x00000000, //OspmFlags + EFI_ACPI_RESERVED_BYTE, //Reserved1[24] + 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 executable + // + return (VOID*)&FACS; +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/GloblNvs.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/GloblNvs.asl new file mode 100644 index 0000000000..fffc8297c0 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/GloblNvs.asl @@ -0,0 +1,352 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + + + +// Define a Global region of ACPI NVS Region that may be used for any +// type of implementation. The starting offset and size will be fixed +// up by the System BIOS during POST. Note that the Size must be a word +// in size to be fixed up correctly. + +OperationRegion(GNVS,SystemMemory,0xFFFF0000,0xAA55) +Field(GNVS,AnyAcc,Lock,Preserve) +{ + Offset(0), // Miscellaneous Dynamic Registers: + OSYS, 16, // (00) Operating System + , 8, // (02) + , 8, // (03) + , 8, // (04) + , 8, // (05) + , 8, // (06) + , 8, // (07) + , 8, // (08) + , 8, // (09) + , 8, // (10) + P80D, 32, // (11) Port 80 Debug Port Value + LIDS, 8, // (15) Lid State (Lid Open = 1) + , 8, // (16) + , 8, // (17) + Offset(18), // Thermal Policy Registers: + , 8, // (18) + , 8, // (19) + ACTT, 8, // (20) Active Trip Point + PSVT, 8, // (21) Passive Trip Point + TC1V, 8, // (22) Passive Trip Point TC1 Value + TC2V, 8, // (23) Passive Trip Point TC2 Value + TSPV, 8, // (24) Passive Trip Point TSP Value + CRTT, 8, // (25) Critical Trip Point + DTSE, 8, // (26) Digital Thermal Sensor Enable + DTS1, 8, // (27) Digital Thermal Sensor 1 Reading + DTS2, 8, // (28) Digital Thermal Sensor 2 Reading + DTSF, 8, // (29) DTS SMI Function Call + Offset(30), // Battery Support Registers: + , 8, // (30) + , 8, // (31) + , 8, // (32) + , 8, // (33) + , 8, // (34) + , 8, // (35) + , 8, // (36) + Offset(40), // CPU Identification Registers: + APIC, 8, // (40) APIC Enabled by SBIOS (APIC Enabled = 1) + MPEN, 8, // (41) Number of Logical Processors if MP Enabled != 0 + , 8, // (42) + , 8, // (43) + , 8, // (44) + , 32, // (45) + Offset(50), // SIO CMOS Configuration Registers: + , 8, // (50) + , 8, // (51) + , 8, // (52) + , 8, // (53) + , 8, // (54) + , 8, // (55) + , 8, // (56) + , 8, // (57) + , 8, // (58) + Offset(60), // Internal Graphics Registers: + , 8, // (60) + , 8, // (61) + CADL, 8, // (62) Current Attached Device List + , 8, // (63) + CSTE, 16, // (64) Current Display State + NSTE, 16, // (66) Next Display State + , 16, // (68) + NDID, 8, // (70) Number of Valid Device IDs + DID1, 32, // (71) Device ID 1 + DID2, 32, // (75) Device ID 2 + DID3, 32, // (79) Device ID 3 + DID4, 32, // (83) Device ID 4 + DID5, 32, // (87) Device ID 5 + , 32, // (91) + , 8, // (95) Fifth byte of AKSV (mannufacturing mode) + Offset(103), // Backlight Control Registers: + , 8, // (103) + BRTL, 8, // (104) Brightness Level Percentage + Offset(105), // Ambiant Light Sensor Registers: + , 8, // (105) + , 8, // (106) + LLOW, 8, // (107) LUX Low Value + , 8, // (108) + Offset(110), // EMA Registers: + , 8, // (110) + , 16, // (111) + , 16, // (113) + Offset(116), // MEF Registers: + , 8, // (116) MEF Enable + Offset(117), // PCIe Dock: + , 8, // (117) + Offset(120), // TPM Registers: + , 8, // (120) + , 8, // (121) + , 8, // (122) + , 8, // (123) + , 32, // (124) + , 8, // (125) + , 8, // (129) + Offset(130), // + , 56, // (130) + , 56, // (137) + , 8, // (144) + , 56, // (145) + Offset(170), // IGD OpRegion/Software SCI base address + ASLB, 32, // (170) IGD OpRegion base address + Offset(174), // IGD OpRegion/Software SCI shared data + IBTT, 8, // (174) IGD Boot Display Device + IPAT, 8, // (175) IGD Panel Type CMOs option + ITVF, 8, // (176) IGD TV Format CMOS option + ITVM, 8, // (177) IGD TV Minor Format CMOS option + IPSC, 8, // (178) IGD Panel Scaling + IBLC, 8, // (179) IGD BLC Configuration + IBIA, 8, // (180) IGD BIA Configuration + ISSC, 8, // (181) IGD SSC Configuration + I409, 8, // (182) IGD 0409 Modified Settings Flag + I509, 8, // (183) IGD 0509 Modified Settings Flag + I609, 8, // (184) IGD 0609 Modified Settings Flag + I709, 8, // (185) IGD 0709 Modified Settings Flag + IDMM, 8, // (186) IGD DVMT Mode + IDMS, 8, // (187) IGD DVMT Memory Size + IF1E, 8, // (188) IGD Function 1 Enable + HVCO, 8, // (189) HPLL VCO + NXD1, 32, // (190) Next state DID1 for _DGS + NXD2, 32, // (194) Next state DID2 for _DGS + NXD3, 32, // (198) Next state DID3 for _DGS + NXD4, 32, // (202) Next state DID4 for _DGS + NXD5, 32, // (206) Next state DID5 for _DGS + NXD6, 32, // (210) Next state DID6 for _DGS + NXD7, 32, // (214) Next state DID7 for _DGS + NXD8, 32, // (218) Next state DID8 for _DGS + GSMI, 8, // (222) GMCH SMI/SCI mode (0=SCI) + PAVP, 8, // (223) IGD PAVP data + Offset(225), + OSCC, 8, // (225) PCIE OSC Control + NEXP, 8, // (226) Native PCIE Setup Value + Offset(235), // Global Variables + DSEN, 8, // (235) _DOS Display Support Flag. + ECON, 8, // (236) Embedded Controller Availability Flag. + GPIC, 8, // (237) Global IOAPIC/8259 Interrupt Mode Flag. + CTYP, 8, // (238) Global Cooling Type Flag. + L01C, 8, // (239) Global L01 Counter. + VFN0, 8, // (240) Virtual Fan0 Status. + VFN1, 8, // (241) Virtual Fan1 Status. + Offset(256), + NVGA, 32, // (256) NVIG opregion address + NVHA, 32, // (260) NVHM opregion address + AMDA, 32, // (264) AMDA opregion address + DID6, 32, // (268) Device ID 6 + DID7, 32, // (272) Device ID 7 + DID8, 32, // (276) Device ID 8 + Offset(332), + USEL, 8, // (332) UART Selection + PU1E, 8, // (333) PCU UART 1 Enabled + PU2E, 8, // (334) PCU UART 2 Enabled + + LPE0, 32, // (335) LPE Bar0 + LPE1, 32, // (339) LPE Bar1 + LPE2, 32, // (343) LPE Bar2 + + Offset(347), + , 8, // (347) + , 8, // (348) + PFLV, 8, // (349) Platform Flavor + + Offset(351), + ICNF, 8, // (351) ISCT / AOAC Configuration + XHCI, 8, // (352) xHCI controller mode + PMEN, 8, // (353) PMIC enable/disable + + LPEE, 8, // (354) LPE enable/disable + ISPA, 32, // (355) ISP Base Addr + ISPD, 8, // (359) ISP Device Selection 0: Disabled; 1: PCI Device 2; 2: PCI Device 3 + + offset(360), // ((4+8+6)*4+2)*4=296 + // + // Lpss controllers + // + PCIB, 32, + PCIT, 32, + D10A, 32, //DMA1 + D10L, 32, + D11A, 32, + D11L, 32, + P10A, 32, // PWM1 + P10L, 32, + P11A, 32, + P11L, 32, + P20A, 32, // PWM2 + P20L, 32, + P21A, 32, + P21L, 32, + U10A, 32, // UART1 + U10L, 32, + U11A, 32, + U11L, 32, + U20A, 32, // UART2 + U20L, 32, + U21A, 32, + U21L, 32, + SP0A, 32, // SPI + SP0L, 32, + SP1A, 32, + SP1L, 32, + + D20A, 32, //DMA2 + D20L, 32, + D21A, 32, + D21L, 32, + I10A, 32, // I2C1 + I10L, 32, + I11A, 32, + I11L, 32, + I20A, 32, // I2C2 + I20L, 32, + I21A, 32, + I21L, 32, + I30A, 32, // I2C3 + I30L, 32, + I31A, 32, + I31L, 32, + I40A, 32, // I2C4 + I40L, 32, + I41A, 32, + I41L, 32, + I50A, 32, // I2C5 + I50L, 32, + I51A, 32, + I51L, 32, + I60A, 32, // I2C6 + I60L, 32, + I61A, 32, + I61L, 32, + I70A, 32, // I2C7 + I70L, 32, + I71A, 32, + I71L, 32, + // + // Scc controllers + // + eM0A, 32, // EMMC + eM0L, 32, + eM1A, 32, + eM1L, 32, + SI0A, 32, // SDIO + SI0L, 32, + SI1A, 32, + SI1L, 32, + SD0A, 32, // SDCard + SD0L, 32, + SD1A, 32, + SD1L, 32, + MH0A, 32, // + MH0L, 32, + MH1A, 32, + MH1L, 32, + + offset(656), + SDRM, 8, + offset(657), + HLPS, 8, //(657) Hide Devices + offset(658), + OSEL, 8, //(658) OS Seletion - Windows/Android + + offset(659), // VLV1 DPTF + SDP1, 8, //(659) An enumerated value corresponding to SKU + DPTE, 8, //(660) DPTF Enable + THM0, 8, //(661) System Thermal 0 + THM1, 8, //(662) System Thermal 1 + THM2, 8, //(663) System Thermal 2 + THM3, 8, //(664) System Thermal 3 + THM4, 8, //(665) System Thermal 3 + CHGR, 8, //(666) DPTF Changer Device + DDSP, 8, //(667) DPTF Display Device + DSOC, 8, //(668) DPTF SoC device + DPSR, 8, //(669) DPTF Processor device + DPCT, 32, //(670) DPTF Processor participant critical temperature + DPPT, 32, //(674) DPTF Processor participant passive temperature + DGC0, 32, //(678) DPTF Generic sensor0 participant critical temperature + DGP0, 32, //(682) DPTF Generic sensor0 participant passive temperature + DGC1, 32, //(686) DPTF Generic sensor1 participant critical temperature + DGP1, 32, //(690) DPTF Generic sensor1 participant passive temperature + DGC2, 32, //(694) DPTF Generic sensor2 participant critical temperature + DGP2, 32, //(698) DPTF Generic sensor2 participant passive temperature + DGC3, 32, //(702) DPTF Generic sensor3 participant critical temperature + DGP3, 32, //(706) DPTF Generic sensor3 participant passive temperature + DGC4, 32, //(710)DPTF Generic sensor3 participant critical temperature + DGP4, 32, //(714)DPTF Generic sensor3 participant passive temperature + DLPM, 8, //(718) DPTF Current low power mode setting + DSC0, 32, //(719) DPTF Critical threshold0 for SCU + DSC1, 32, //(723) DPTF Critical threshold1 for SCU + DSC2, 32, //(727) DPTF Critical threshold2 for SCU + DSC3, 32, //(731) DPTF Critical threshold3 for SCU + DSC4, 32, //(735) DPTF Critical threshold3 for SCU + DDBG, 8, //(739) DPTF Super Debug option. 0 - Disabled, 1 - Enabled + LPOE, 32, //(740) DPTF LPO Enable + LPPS, 32, //(744) P-State start index + LPST, 32, //(748) Step size + LPPC, 32, //(752) Power control setting + LPPF, 32, //(756) Performance control setting + DPME, 8, //(760) DPTF DPPM enable/disable + BCSL, 8, //(761) Battery charging solution 0-CLV 1-ULPMC + NFCS, 8, //(762) NFCx Select 1: NFC1 2:NFC2 + PCIM, 8, //(763) EMMC device 0-ACPI mode, 1-PCI mode + TPMA, 32, //(764) + TPML, 32, //(768) + ITSA, 8, //(772) I2C Touch Screen Address + S0IX, 8, //(773) S0ix status + SDMD, 8, //(774) SDIO Mode + EMVR, 8, //(775) eMMC controller version + BMBD, 32, //(776) BM Bound + FSAS, 8, //(780) FSA Status + BDID, 8, //(781) Board ID + FBID, 8, //(782) FAB ID + OTGM, 8, //(783) OTG mode + STEP, 8, //(784) Stepping ID + WITT, 8, //(785) Enable Test Device connected to I2C for WHCK test. + SOCS, 8, //(786) provide the SoC stepping infomation + AMTE, 8, //(787) Ambient Trip point change + UTS, 8, //(788) Enable Test Device connected to URT for WHCK test. + SCPE, 8, //(789) Allow higher performance on AC/USB - Enable/Disable + Offset(792), + EDPV, 8, //(792) Check for eDP display device + DIDX, 32, //(793) Device ID for eDP device + IOT, 8, //(794) MinnowBoard Max JP1 is configured for MSFT IOT project. +} + diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Gpe.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Gpe.asl new file mode 100644 index 0000000000..17535401fe --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Gpe.asl @@ -0,0 +1,105 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + + +// General Purpose Events. This Scope handles the Run-time and +// Wake-time SCIs. The specific method called will be determined by +// the _Lxx value, where xx equals the bit location in the General +// Purpose Event register(s). + +Scope(\_GPE) +{ + // + // Software GPE caused the event. + // + Method(_L02) + { + // Clear GPE status bit. + Store(0,GPEC) + // + // Handle DTS Thermal Events. + // + External(DTSE, IntObj) + If(CondRefOf(DTSE)) + { + If(LGreaterEqual(DTSE, 0x01)) + { + Notify(\_TZ.TZ01,0x80) + } + } + } + + // + // PUNIT SCI event. + // + Method(_L04) + { + // Clear the PUNIT Status Bit. + Store(1, PSCI) + } + + + // + // IGD OpRegion SCI event (see IGD OpRegion/Software SCI BIOS SPEC). + // + Method(_L05) + { + If(LAnd(\_SB.PCI0.GFX0.GSSE, LNot(GSMI))) // Graphics software SCI event? + { + \_SB.PCI0.GFX0.GSCI() // Handle the SWSCI + } + } + + // + // This PME event (PCH's GPE #13) is received when any PCH internal device with PCI Power Management capabilities + // on bus 0 asserts the equivalent of the PME# signal. + // + Method(_L0D, 0) + { + If(LAnd(\_SB.PCI0.EHC1.PMEE, \_SB.PCI0.EHC1.PMES)) + { + If(LNotEqual(OSEL, 1)) + { + Store(1, \_SB.PCI0.EHC1.PMES) //Clear PME status + Store(0, \_SB.PCI0.EHC1.PMEE) //Disable PME + } + Notify(\_SB.PCI0.EHC1, 0x02) + } + If(LAnd(\_SB.PCI0.XHC1.PMEE, \_SB.PCI0.XHC1.PMES)) + { + If(LNotEqual(OSEL, 1)) + { + Store(1, \_SB.PCI0.XHC1.PMES) //Clear PME status + Store(0, \_SB.PCI0.XHC1.PMEE) //Disable PME + } + Notify(\_SB.PCI0.XHC1, 0x02) + } + If(LAnd(\_SB.PCI0.HDEF.PMEE, \_SB.PCI0.HDEF.PMES)) + { + If(LNotEqual(OSEL, 1)) + { + Store(1, \_SB.PCI0.HDEF.PMES) //Clear PME status + Store(0, \_SB.PCI0.HDEF.PMEE) //Disable PME + } + Notify(\_SB.PCI0.HDEF, 0x02) + } + } +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/HOST_BUS.ASL b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/HOST_BUS.ASL new file mode 100644 index 0000000000..587909b1e6 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/HOST_BUS.ASL @@ -0,0 +1,353 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + HOST_BUS.ASL + +Abstract: + + Baytrail PCI configuration space definition. + +---*/ +Device(VLVC) +{ + Name(_ADR, 0x00000000) // Device 0, Function 0 + + // Define various MCH Controller PCI Configuration Space + // registers which will be used to dynamically produce all + // resources in the Host Bus _CRS. + OperationRegion(HBUS, PCI_Config, 0x00, 0xFF) + Field(HBUS, DWordAcc, NoLock, Preserve) + { + Offset(0xD0), + SMCR, 32, // VLV Message Control Register (0xD0) + Offset(0xD4), + SMDR, 32, // VLV Message Data Register (0xD4) + Offset(0xD8), + MCRX, 32, // VLV Message Control Register Extension (0xD8) + } + + // Define a method to read a 32-bit register on the VLV Message bus. + // Arg0 = Port + // Arg1 = Register + // + // Returns 32-bit register value + + Method(RMBR, 2, Serialized) + { + + // Initiate regsiter read message on VLV Message Bus MCR + + Or(ShiftLeft(Arg0, 16), ShiftLeft(Arg1, 8), Local0) + Or(0x100000F0, Local0, SMCR) + + // Read register value from Message Data Register + + Return(SMDR) + } + + + // Define a method to write a 32-bit register on the VLV Message bus MDR. + // Arg0 = Port + // Arg1 = Register + // Arg2 = 32-bit value + + Method(WMBR, 3, Serialized) + { + + // Write register value to Message Data Register + + Store(Arg2, SMDR) + + // Initiate register write message on VLV Message Bus + + Or(ShiftLeft(Arg0, 16), ShiftLeft(Arg1, 8), Local0) + Or(0x110000F0, Local0, SMCR) + } +} + +// +// BUS, I/O, and MMIO resources +// +Method(_CRS,0,Serialized) +{ + //Update ISP0 reserved memory + CreateDwordField(RES0, ^ISP0._MIN,ISMN) + CreateDwordField(RES0, ^ISP0._MAX,ISMX) + CreateDwordField(RES0, ^ISP0._LEN,ISLN) + If (LEqual(ISPD,1)) + { + Store (ISPA, ISMN) + Add (ISMN, ISLN, ISMX) + Subtract(ISMX, 1, ISMX) + } Else + { + Store (0, ISMN) + Store (0, ISMX) + Store (0, ISLN) + } + + //PCI MMIO SPACE + CreateDwordField(RES0, ^PM01._MIN,M1MN) + CreateDwordField(RES0, ^PM01._MAX,M1MX) + CreateDwordField(RES0, ^PM01._LEN,M1LN) + + //Get dBMBOUND Base + And(BMBD, 0xFF000000, M1MN) + + //Get ECBASE + Store(PCIT, M1MX) + Add(Subtract(M1MX, M1MN), 1, M1LN) + Subtract(M1MX, 1, M1MX) + + // Create pointers to Gfx Stolen Memory Sizing values. + CreateDwordField(RES0, ^STOM._MIN,GSMN) + CreateDwordField(RES0, ^STOM._MAX,GSMX) + CreateDwordField(RES0, ^STOM._LEN,GSLN) + + If (LNotEqual (\_SB.PCI0.GFX0.GSTM, 0xFFFFFFFF)) + { + Store(0x00, GSMN) //Read the Stolen memory base from B0:D2:F0:R5C + } else + { + Store(\_SB.PCI0.GFX0.GSTM, GSMN) //Read the Stolen memory base from B0:D2:F0:R5C + } + If (LNotEqual (\_SB.PCI0.GFX0.GUMA, 0xFFFFFFFF)) + { + Store(0x00, GSLN) //Read the Stolen memory base from B0:D2:F0:R5C + } else + { + ShiftLeft(\_SB.PCI0.GFX0.GUMA, 25, GSLN) //Read Stolen memory base form B0:D2:F0:R50 + } + Add(GSMN, GSLN, GSMX) //Store the Stolen Memory Size + Subtract(GSMX, 1, GSMX) + + Return(RES0) +} + +Name( RES0,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 + 0x00FF, // Max + 0x0000, // Translation + 0x0100 // Range Length = Max-Min+1 + ) + + IO (Decode16, 0x70, 0x77, 0x01, 0x08) //Consumed resource (0xCF8-0xCFF) + IO (Decode16, 0xCF8, 0xCF8, 0x01, 0x08) //Consumed resource (0xCF8-0xCFF) + + 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 + 0x006F, // Max + 0x0000, // Translation + 0x0070 // Range Length + ) + + WORDIO ( // Consumed-and-produced resource + ResourceProducer, // bit 0 of general flags is 0 + MinFixed, // Range is fixed + MaxFixed, // Range is fixed + PosDecode, + EntireRange, + 0x0000, // Granularity + 0x0078, // Min + 0x0CF7, // Max + 0x0000, // Translation + 0x0C80 // Range Length + ) + + 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 legacy VGA video RAM + 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 ( // Descriptor for legacy OptionRom + ResourceProducer, // bit 0 of general flags is 0 + PosDecode, + MinFixed, // Range is fixed + MaxFixed, // Range is fixed + Cacheable, + ReadWrite, + 0x00000000, // Granularity + 0x000C0000, // Min + 0x000DFFFF, // Max + 0x00000000, // Translation + 0x00020000 // Range Length + ) + + DWORDMEMORY ( // Descriptor for BIOS Area + ResourceProducer, // bit 0 of general flags is 0 + PosDecode, + MinFixed, // Range is fixed + MaxFixed, // Range is fixed + Cacheable, + ReadWrite, + 0x00000000, // Granularity + 0x000E0000, // Min + 0x000FFFFF, // Max + 0x00000000, // Translation + 0x00020000 // Range Length + ) + + DWORDMEMORY ( // Descriptor for ISP0 reserved Mem + ResourceProducer, // bit 0 of general flags is 0 + PosDecode, + MinFixed, // Range is fixed + MaxFixed, // Range is fixed + Cacheable, + ReadWrite, + 0x00000000, // Granularity + 0x7A000000, // Min + 0x7A3FFFFF, // Max + 0x00000000, // Translation + 0x00400000 // Range Length + ,,, + ISP0 + ) + + DWORDMEMORY ( // Descriptor for VGA Stolen Mem + ResourceProducer, // bit 0 of general flags is 0 + PosDecode, + MinFixed, // Range is fixed + MaxFixed, // Range is fixed + Cacheable, + ReadWrite, + 0x00000000, // Granularity + 0x7C000000, // Min + 0x7FFFFFFF, // Max + 0x00000000, // Translation + 0x04000000 // Range Length + ,,, + STOM + ) + + DWORDMEMORY ( // Descriptor for PCI MMIO + ResourceProducer, // bit 0 of general flags is 0 + PosDecode, + MinFixed, // Range is fixed + MaxFixed, // Range is fixed + Cacheable, + ReadWrite, + 0x00000000, // Granularity + 0x80000000, // Min + 0xDFFFFFFF, // Max + 0x00000000, // Translation + 0x60000000 // Range Length + ,,, + PM01 + ) +}) + +//Name(GUID,UUID("33DB4D5B-1FF7-401C-9657-7441C03DD766")) +Name(GUID,Buffer() +{ + 0x5b, 0x4d, 0xdb, 0x33, + 0xf7, 0x1f, + 0x1c, 0x40, + 0x96, 0x57, + 0x74, 0x41, 0xc0, 0x3d, 0xd7, 0x66 +}) + + +Name(SUPP,0) // PCI _OSC Support Field value +Name(CTRL,0) // PCI _OSC Control Field value + +Method(_OSC,4,Serialized) +{ + // Check for proper UUID + // Save the capabilities buffer + Store(Arg3,Local0) + + // Create DWord-adressable fields from the Capabilties Buffer + CreateDWordField(Local0,0,CDW1) + CreateDWordField(Local0,4,CDW2) + CreateDWordField(Local0,8,CDW3) + + // Check for proper UUID + If(LAnd(LEqual(Arg0,GUID),NEXP)) + { + // Save Capabilities DWord2 & 3 + Store(CDW2,SUPP) + Store(CDW3,CTRL) + + If(Not(And(CDW1,1))) // Query flag clear? + { + // Disable GPEs for features granted native control. + If(And(CTRL,0x02)) + { + NHPG() + } + If(And(CTRL,0x04)) // PME control granted? + { + NPME() + } + } + + If(LNotEqual(Arg1,One)) + { + // Unknown revision + Or(CDW1,0x08,CDW1) + } + + If(LNotEqual(CDW3,CTRL)) + { + // Capabilities bits were masked + Or(CDW1,0x10,CDW1) + } + // Update DWORD3 in the buffer + And(CTRL,0xfe,CTRL) + Store(CTRL,CDW3) + Store(CTRL,OSCC) + Return(Local0) + } Else + { + Or(CDW1,4,CDW1) // Unrecognized UUID + Return(Local0) + } +} // End _OSC diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Hpet/Hpet.aslc b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Hpet/Hpet.aslc new file mode 100644 index 0000000000..d3988cadf5 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Hpet/Hpet.aslc @@ -0,0 +1,69 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Hpet.c + +Abstract: + + This file contains a structure definition for the ACPI HPET Table. +--*/ + +// +// Statements that include other files +// +#ifdef ECP_FLAG +#include +#endif +#include +#include "AcpiTablePlatform.h" + +// Hpet Table +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, + 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 + EFI_ACPI_CREATOR_ID, // ASL compiler vendor ID + EFI_ACPI_CREATOR_REVISION // ASL compiler revision number + }, + 0x0, // EventTimerBlockId + { + 0x00, // Address_Space_ID = System Memory + 0x40, // Register_Bit_Width = 32 bits, mentioned about write failures when in 64bit in SCU HAS + 0x00, // Register_Bit_offset + 0x00, // Dword access + HPET_BASE_ADDRESS, // Base addresse of HPET + }, + 0x0, // Only HPET's _UID in Namespace + MAIN_COUNTER_MIN_PERIODIC_CLOCK_TICKS, + 0x0 +}; + +VOID* +ReferenceAcpiTable ( + VOID + ) +{ + // + // Reference the table being generated to prevent the optimizer from + // removing the data structure from the executable + // + return (VOID*)&HPET; +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/INTELGFX.ASL b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/INTELGFX.ASL new file mode 100644 index 0000000000..c8f663a847 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/INTELGFX.ASL @@ -0,0 +1,885 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + INTELGFX.ASL + +Abstract: + + IGD OpRegion/Software ACPI Reference Code for the Baytrail Family. + +--*/ + +// Enable/Disable Output Switching. In WIN2K/WINXP, _DOS = 0 will +// get called during initialization to prepare for an ACPI Display +// Switch Event. During an ACPI Display Switch, the OS will call +// _DOS = 2 immediately after a Notify=0x80 to temporarily disable +// all Display Switching. After ACPI Display Switching is complete, +// the OS will call _DOS = 0 to re-enable ACPI Display Switching. + +Method(_DOS,1) +{ + // Store Display Switching and LCD brightness BIOS control bit + Store(And(Arg0,7),DSEN) +} + +// Enumerate the Display Environment. This method will return +// valid addresses for all display device encoders present in the +// system. The Miniport Driver will reject the addresses for every +// encoder that does not have an attached display device. After +// enumeration is complete, the OS will call the _DGS methods +// during a display switch only for the addresses accepted by the +// Miniport Driver. For hot-insertion and removal of display +// devices, a re-enumeration notification will be required so the +// address of the newly present display device will be accepted by +// the Miniport Driver. + +Method(_DOD, 0, Serialized) +{ + Store(0, NDID) + If(LNotEqual(DIDL, Zero)) + { + Store(SDDL(DIDL),DID1) + } + If(LNotEqual(DDL2, Zero)) + { + Store(SDDL(DDL2),DID2) + } + If(LNotEqual(DDL3, Zero)) + { + Store(SDDL(DDL3),DID3) + } + If(LNotEqual(DDL4, Zero)) + { + Store(SDDL(DDL4),DID4) + } + If(LNotEqual(DDL5, Zero)) + { + Store(SDDL(DDL5),DID5) + } + + // TODO - This level of flexibility is not needed for a true + // OEM design. Simply determine the greatest number of + // encoders the platform will suppport then remove all + // return packages beyond that value. Note that for + // current silicon, the maximum number of encoders + // possible is 5. + + If(LEqual(NDID,1)) + { + If (LNOTEqual (ISPD, 0)) + { + Name(TMP0,Package() {0xFFFFFFFF,0xFFFFFFFF}) + Store(Or(0x10000,DID1),Index(TMP0,0)) + //Add ISP device to GFX0 + Store(0x00020F38, Index(TMP0,1)) + Return(TMP0) + } Else + { + Name(TMP1,Package() {0xFFFFFFFF}) + Store(Or(0x10000,DID1),Index(TMP1,0)) + Return(TMP1) + } + } + + If(LEqual(NDID,2)) + { + If (LNOTEqual (ISPD, 0)) + { + Name(TMP2,Package() {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}) + Store(Or(0x10000,DID1),Index(TMP2,0)) + Store(Or(0x10000,DID2),Index(TMP2,1)) + //Add ISP device to GFX0 + Store(0x00020F38, Index(TMP2,2)) + Return(TMP2) + } Else + { + Name(TMP3,Package() {0xFFFFFFFF, 0xFFFFFFFF}) + Store(Or(0x10000,DID1),Index(TMP3,0)) + Store(Or(0x10000,DID2),Index(TMP3,1)) + Return(TMP3) + } + } + + If(LEqual(NDID,3)) + { + If (LNOTEqual (ISPD, 0)) + { + Name(TMP4,Package() {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF}) + Store(Or(0x10000,DID1),Index(TMP4,0)) + Store(Or(0x10000,DID2),Index(TMP4,1)) + Store(Or(0x10000,DID3),Index(TMP4,2)) + //Add ISP device to GFX0 + Store(0x00020F38, Index(TMP4,3)) + Return(TMP4) + } Else + { + Name(TMP5,Package() {0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF}) + Store(Or(0x10000,DID1),Index(TMP5,0)) + Store(Or(0x10000,DID2),Index(TMP5,1)) + Store(Or(0x10000,DID3),Index(TMP5,2)) + Return(TMP5) + } + } + + If(LEqual(NDID,4)) + { + If (LNOTEqual (ISPD, 0)) + { + Name(TMP6,Package() {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}) + Store(Or(0x10000,DID1),Index(TMP6,0)) + Store(Or(0x10000,DID2),Index(TMP6,1)) + Store(Or(0x10000,DID3),Index(TMP6,2)) + Store(Or(0x10000,DID4),Index(TMP6,3)) + //Add ISP device to GFX0 + Store(0x00020F38, Index(TMP6,4)) + Return(TMP6) + } Else + { + Name(TMP7,Package() {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}) + Store(Or(0x10000,DID1),Index(TMP7,0)) + Store(Or(0x10000,DID2),Index(TMP7,1)) + Store(Or(0x10000,DID3),Index(TMP7,2)) + Store(Or(0x10000,DID4),Index(TMP7,3)) + Return(TMP7) + } + } + + If(LGreater(NDID,4)) + { + If (LNOTEqual (ISPD, 0)) + { + Name(TMP8,Package() {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}) + Store(Or(0x10000,DID1),Index(TMP8,0)) + Store(Or(0x10000,DID2),Index(TMP8,1)) + Store(Or(0x10000,DID3),Index(TMP8,2)) + Store(Or(0x10000,DID4),Index(TMP8,3)) + Store(Or(0x10000,DID5),Index(TMP8,4)) + //Add ISP device to GFX0 + Store(0x00020F38, Index(TMP8,5)) + Return(TMP8) + } Else + { + Name(TMP9,Package() {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}) + Store(Or(0x10000,DID1),Index(TMP9,0)) + Store(Or(0x10000,DID2),Index(TMP9,1)) + Store(Or(0x10000,DID3),Index(TMP9,2)) + Store(Or(0x10000,DID4),Index(TMP9,3)) + Store(Or(0x10000,DID5),Index(TMP9,4)) + Return(TMP9) + } + } + + // If nothing else, return Unknown LFP. + // (Prevents compiler warning.) + + //Add ISP device to GFX0 + If (LNOTEqual (ISPD, 0)) + { + Return(Package() {0x00000400, 0x00020F38}) + } Else + { + Return(Package() {0x00000400}) + } +} + +Device(DD01) +{ + + // Return Unique ID. + + Method(_ADR,0,Serialized) + { + If(LEqual(And(0x0F00,DID1),0x400)) + { + Store(0x1, EDPV) + Store(DID1, DIDX) + Return(1) + } + If(LEqual(DID1,0)) + { + Return(1) + } + Else + { + Return(And(0xFFFF,DID1)) + } + } + + // Return the Current Status. + + Method(_DCS,0) + { + Return(CDDS(DID1)) + } + + // Query Graphics State (active or inactive). + + Method(_DGS,0) + { + Return(NDDS(DID1)) + } + + // Device Set State. + + // _DSS Table: + // + // BIT31 BIT30 Execution + // 0 0 Don't implement. + // 0 1 Cache change. Nothing to Implement. + // 1 0 Don't Implement. + // 1 1 Display Switch Complete. Implement. + + Method(_DSS,1) + { + If(LEqual(And(Arg0,0xC0000000),0xC0000000)) + { + + // State change was performed by the + // Video Drivers. Simply update the + // New State. + + Store(NSTE,CSTE) + } + } +} + +Device(DD02) +{ + + // Return Unique ID. + + Method(_ADR,0,Serialized) + { + If(LEqual(And(0x0F00,DID2),0x400)) + { + Store(0x2, EDPV) + Store(DID2, DIDX) + Return(2) + } + If(LEqual(DID2,0)) + { + Return(2) + } + Else + { + Return(And(0xFFFF,DID2)) + } + } + + // Return the Current Status. + + Method(_DCS,0) + { + Return(CDDS(DID2)) + } + + // Query Graphics State (active or inactive). + + Method(_DGS,0) + { + // Return the Next State. + Return(NDDS(DID2)) + } + + // Device Set State. (See table above.) + + Method(_DSS,1) + { + If(LEqual(And(Arg0,0xC0000000),0xC0000000)) + { + + // State change was performed by the + // Video Drivers. Simply update the + // New State. + + Store(NSTE,CSTE) + } + } +} + +Device(DD03) +{ + + // Return Unique ID. + + Method(_ADR,0,Serialized) + { + If(LEqual(And(0x0F00,DID3),0x400)) + { + Store(0x3, EDPV) + Store(DID3, DIDX) + Return(3) + } + If(LEqual(DID3,0)) + { + Return(3) + } + Else + { + Return(And(0xFFFF,DID3)) + } + } + + // Return the Current Status. + + Method(_DCS,0) + { + If(LEqual(DID3,0)) + { + Return(0x0B) + } + Else + { + Return(CDDS(DID3)) + } + } + + // Query Graphics State (active or inactive). + + Method(_DGS,0) + { + Return(NDDS(DID3)) + } + + // Device Set State. (See table above.) + + Method(_DSS,1) + { + If(LEqual(And(Arg0,0xC0000000),0xC0000000)) + { + // State change was performed by the + // Video Drivers. Simply update the + // New State. + + Store(NSTE,CSTE) + } + } +} + +Device(DD04) +{ + + // Return Unique ID. + + Method(_ADR,0,Serialized) + { + If(LEqual(And(0x0F00,DID4),0x400)) + { + Store(0x4, EDPV) + Store(DID4, DIDX) + Return(4) + } + If(LEqual(DID4,0)) + { + Return(4) + } + Else + { + Return(And(0xFFFF,DID4)) + } + } + + // Return the Current Status. + + Method(_DCS,0) + { + If(LEqual(DID4,0)) + { + Return(0x0B) + } + Else + { + Return(CDDS(DID4)) + } + } + + // Query Graphics State (active or inactive). + + Method(_DGS,0) + { + Return(NDDS(DID4)) + } + + // Device Set State. (See table above.) + + Method(_DSS,1) + { + If(LEqual(And(Arg0,0xC0000000),0xC0000000)) + { + + // State change was performed by the + // Video Drivers. Simply update the + // New State. + + Store(NSTE,CSTE) + } + } +} + + +Device(DD05) +{ + + // Return Unique ID. + + Method(_ADR,0,Serialized) + { + If(LEqual(And(0x0F00,DID5),0x400)) + { + Store(0x5, EDPV) + Store(DID5, DIDX) + Return(5) + } + If(LEqual(DID5,0)) + { + Return(5) + } + Else + { + Return(And(0xFFFF,DID5)) + } + } + + // Return the Current Status. + + Method(_DCS,0) + { + If(LEqual(DID5,0)) + { + Return(0x0B) + } + Else + { + Return(CDDS(DID5)) + } + } + + // Query Graphics State (active or inactive). + + Method(_DGS,0) + { + Return(NDDS(DID5)) + } + + // Device Set State. (See table above.) + + Method(_DSS,1) + { + If(LEqual(And(Arg0,0xC0000000),0xC0000000)) + { + // State change was performed by the + // Video Drivers. Simply update the + // New State. + + Store(NSTE,CSTE) + } + } +} + + +Device(DD06) +{ + + // Return Unique ID. + + Method(_ADR,0,Serialized) + { + If(LEqual(And(0x0F00,DID6),0x400)) + { + Store(0x6, EDPV) + Store(DID6, DIDX) + Return(6) + } + If(LEqual(DID6,0)) + { + Return(6) + } + Else + { + Return(And(0xFFFF,DID6)) + } + } + + // Return the Current Status. + + Method(_DCS,0) + { + If(LEqual(DID6,0)) + { + Return(0x0B) + } + Else + { + Return(CDDS(DID6)) + } + } + + // Query Graphics State (active or inactive). + + Method(_DGS,0) + { + Return(NDDS(DID6)) + } + + // Device Set State. (See table above.) + + Method(_DSS,1) + { + If(LEqual(And(Arg0,0xC0000000),0xC0000000)) + { + // State change was performed by the + // Video Drivers. Simply update the + // New State. + + Store(NSTE,CSTE) + } + } +} + + +Device(DD07) +{ + + // Return Unique ID. + + Method(_ADR,0,Serialized) + { + If(LEqual(And(0x0F00,DID7),0x400)) + { + Store(0x7, EDPV) + Store(DID7, DIDX) + Return(7) + } + If(LEqual(DID7,0)) + { + Return(7) + } + Else + { + Return(And(0xFFFF,DID7)) + } + } + + // Return the Current Status. + + Method(_DCS,0) + { + If(LEqual(DID7,0)) + { + Return(0x0B) + } + Else + { + Return(CDDS(DID7)) + } + } + + // Query Graphics State (active or inactive). + + Method(_DGS,0) + { + Return(NDDS(DID7)) + } + + // Device Set State. (See table above.) + + Method(_DSS,1) + { + If(LEqual(And(Arg0,0xC0000000),0xC0000000)) + { + // State change was performed by the + // Video Drivers. Simply update the + // New State. + + Store(NSTE,CSTE) + } + } +} + + +Device(DD08) +{ + + // Return Unique ID. + + Method(_ADR,0,Serialized) + { + If(LEqual(And(0x0F00,DID8),0x400)) + { + Store(0x8, EDPV) + Store(DID8, DIDX) + Return(8) + } + If(LEqual(DID8,0)) + { + Return(8) + } + Else + { + Return(And(0xFFFF,DID8)) + } + } + + // Return the Current Status. + + Method(_DCS,0) + { + If(LEqual(DID8,0)) + { + Return(0x0B) + } + Else + { + Return(CDDS(DID8)) + } + } + + // Query Graphics State (active or inactive). + + Method(_DGS,0) + { + Return(NDDS(DID8)) + } + + // Device Set State. (See table above.) + + Method(_DSS,1) + { + If(LEqual(And(Arg0,0xC0000000),0xC0000000)) + { + // State change was performed by the + // Video Drivers. Simply update the + // New State. + + Store(NSTE,CSTE) + } + } +} + +//device for eDP +Device(DD1F) +{ + // Return Unique ID. + + Method(_ADR,0,Serialized) + { + If(LEqual(EDPV, 0x0)) + { + Return(0x1F) + } + Else + { + Return(And(0xFFFF,DIDX)) + } + } + + // Return the Current Status. + + Method(_DCS,0) + { + If(LEqual(EDPV, 0x0)) + { + Return(0x00) + } + Else + { + Return(CDDS(DIDX)) + } + } + + // Query Graphics State (active or inactive). + + Method(_DGS,0) + { + Return(NDDS(DIDX)) + } + + // Device Set State. (See table above.) + + Method(_DSS,1) + { + If(LEqual(And(Arg0,0xC0000000),0xC0000000)) + { + // State change was performed by the + // Video Drivers. Simply update the + // New State. + Store(NSTE,CSTE) + } + } + // Query List of Brightness Control Levels Supported. + + Method(_BCL,0) + { + // List of supported brightness levels in the following sequence. + + // Level when machine has full power. + // Level when machine is on batteries. + // Other supported levels. + Return(Package() {80, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100}) + } + + // Set the Brightness Level. + + Method (_BCM,1) + { + // Set the requested level if it is between 0 and 100%. + + If(LAnd(LGreaterEqual(Arg0,0),LLessEqual(Arg0,100))) + { + \_SB.PCI0.GFX0.AINT(1, Arg0) + Store(Arg0,BRTL) // Store Brightness Level. + } + } + + // Brightness Query Current level. + + Method (_BQC,0) + { + Return(BRTL) + } +} + +Method(SDDL,1) +{ + Increment(NDID) + Store(And(Arg0,0xF0F),Local0) + Or(0x80000000,Local0, Local1) + If(LEqual(DIDL,Local0)) + { + Return(Local1) + } + If(LEqual(DDL2,Local0)) + { + Return(Local1) + } + If(LEqual(DDL3,Local0)) + { + Return(Local1) + } + If(LEqual(DDL4,Local0)) + { + Return(Local1) + } + If(LEqual(DDL5,Local0)) + { + Return(Local1) + } + If(LEqual(DDL6,Local0)) + { + Return(Local1) + } + If(LEqual(DDL7,Local0)) + { + Return(Local1) + } + If(LEqual(DDL8,Local0)) + { + Return(Local1) + } + Return(0) +} + +Method(CDDS,1) +{ + Store(And(Arg0,0xF0F),Local0) + + If(LEqual(0, Local0)) + { + Return(0x1D) + } + If(LEqual(CADL, Local0)) + { + Return(0x1F) + } + If(LEqual(CAL2, Local0)) + { + Return(0x1F) + } + If(LEqual(CAL3, Local0)) + { + Return(0x1F) + } + If(LEqual(CAL4, Local0)) + { + Return(0x1F) + } + If(LEqual(CAL5, Local0)) + { + Return(0x1F) + } + If(LEqual(CAL6, Local0)) + { + Return(0x1F) + } + If(LEqual(CAL7, Local0)) + { + Return(0x1F) + } + If(LEqual(CAL8, Local0)) + { + Return(0x1F) + } + Return(0x1D) +} + +Method(NDDS,1) +{ + Store(And(Arg0,0xF0F),Local0) + + If(LEqual(0, Local0)) + { + Return(0) + } + If(LEqual(NADL, Local0)) + { + Return(1) + } + If(LEqual(NDL2, Local0)) + { + Return(1) + } + If(LEqual(NDL3, Local0)) + { + Return(1) + } + If(LEqual(NDL4, Local0)) + { + Return(1) + } + If(LEqual(NDL5, Local0)) + { + Return(1) + } + If(LEqual(NDL6, Local0)) + { + Return(1) + } + If(LEqual(NDL7, Local0)) + { + Return(1) + } + If(LEqual(NDL8, Local0)) + { + Return(1) + } + Return(0) +} + +// +// Include IGD OpRegion/Software SCI interrupt handler which is use by +// the graphics drivers to request data from system BIOS. +// +include("IgdOpRn.ASL") diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/INTELISPDev2.ASL b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/INTELISPDev2.ASL new file mode 100644 index 0000000000..280d6cb3d3 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/INTELISPDev2.ASL @@ -0,0 +1,77 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + INTELISPDev2.ASL + +Abstract: + + ISP Exist as B0D2F0 Software ACPI Reference Code for the Baytrail Family. + +--*/ +////Device ISP0 +Device(ISP0) +{ + Name(_ADR, 0x0F38) + //Name (_HID, "80860F38") + //Name (_CID, "80860F38") + Name(_DDN, "VLV2 ISP - 80860F38") + Name(_UID, 0x01) + + Method (_STA, 0, NotSerialized) + { + If(LEqual(ISPD,1)) //Dev2 need report ISP0 as GFX0 child + { + Return (0xF) + } + Else + { + Return (0x0) + } + } + Name(SBUF,ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00400000, ISP0) + }) + Method(_CRS, 0x0, NotSerialized) + { + Return (SBUF) + } + Method (_SRS, 0x1, NotSerialized) + { + } + Method (_DIS, 0x0, NotSerialized) + { + } + Method(_DSM, 0x4, NotSerialized) + { + If (LEqual (Arg0, 0x01)) + { + ///Switch ISP to D3H + Return (0x01) + } + Elseif (LEqual (Arg0, 0x02)) + { + //Switch ISP to D0 + Return (0x02) + } + Else + { + //Do nothing + Return (0x0F) + } + } +} ///End ISP0 + diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOGBDA.ASL b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOGBDA.ASL new file mode 100644 index 0000000000..d4e735e3e6 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOGBDA.ASL @@ -0,0 +1,161 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + IgdOGBDA.ASL + +Abstract: + + IGD OpRegion/Software SCI Reference Code for the Baytrail Family. + This file contains Get BIOS Data Area funciton support for + the Integrated Graphics Device (IGD) OpRegion/Software SCI mechanism. + +--*/ + + +Method (GBDA, 0, Serialized) +{ + + // Supported calls: Sub-function 0 + + If (LEqual(GESF, 0)) + { + // Update implementation specific supported calls. Reference + // code is set to Intel's validated implementation. + + Store(0x0000279, PARM) + + Store(Zero, GESF) // Clear the exit parameter + Return(SUCC) // Success + } + + // Requested callbacks: Sub-function 1 + + If (LEqual(GESF, 1)) + { + + // Update implementation specific system BIOS requested call + // back functions. Call back functions are where the driver calls the + // system BIOS at function indicated event. + + Store(0x00000240, PARM) + + Store(Zero, GESF) // Clear the exit parameter + Return(SUCC) // Success + } + + // Get Boot display Preferences: Sub-function 4 + + If (LEqual(GESF, 4)) + { + + // Update the implementation specific Get Boot Display + // Preferences function. + + And(PARM, 0xEFFF0000, PARM) // PARM[30:16] = Boot device ports + And(PARM, ShiftLeft(DeRefOf(Index(DBTB, IBTT)), 16), PARM) + Or(IBTT, PARM, PARM) // PARM[7:0] = Boot device type + + Store(Zero, GESF) // Clear the exit parameter + Return(SUCC) // Success + } + + // Panel details: Sub-function 5 + + If (LEqual(GESF, 5)) + { + + // Update the implementation specific Get Panel Details + // function. + + Store(IPSC, PARM) // Report the scaling setting + Or(PARM, ShiftLeft(IPAT, 8), PARM) + Add(PARM, 0x100, PARM) // Adjust panel type, 0 = VBT default + Or(PARM, ShiftLeft(LIDS, 16), PARM) // Report the lid state + Add(PARM, 0x10000, PARM) // Adjust the lid state, 0 = Unknown + Or(PARM, ShiftLeft(IBLC, 18), PARM) // Report the BLC setting + Or(PARM, ShiftLeft(IBIA, 20), PARM) // Report the BIA setting + Store(Zero, GESF) + Return(SUCC) + } + + // TV-standard/Video-connector: Sub-function 6 + + If (LEqual(GESF, 6)) + { + + // Update the implementation specific Get + // TV-standard/Video-connectorPanel function. + + Store(ITVF, PARM) + Or(PARM, ShiftLeft(ITVM, 4), PARM) + Store(Zero, GESF) + Return(SUCC) + } + + // Internal graphics: Sub-function 7 + + If (LEqual(GESF, 7)) + { + Store(GIVD, PARM) // PARM[0] - VGA mode(1=VGA) + Xor(PARM, 1, PARM) // Invert the VGA mode polarity + Or(PARM, ShiftLeft(GMFN, 1), PARM) // PARM[1] - # IGD PCI functions-1 + // PARM[3:2] - Reserved + // PARM[4] - IGD D3 support(0=cold) + // PARM[10:5] - Reserved + Or(PARM, ShiftLeft(3, 11), PARM) // PARM[12:11] - DVMT mode(11b = 5.0) + + // + // Report DVMT 5.0 Total Graphics memory size. + // + Or(PARM, ShiftLeft(IDMS, 17), PARM) // Bits 20:17 are for Gfx total memory size + + // If the "Set Internal Graphics" call is supported, the modified + // settings flag must be programmed per the specification. This means + // that the flag must be set to indicate that system BIOS requests + // these settings. Once "Set Internal Graphics" is called, the + // modified settings flag must be cleared on all subsequent calls to + // this function. + + // Report the graphics frequency based on DISPLAY_CLOCK_FREQUENCY_ENCODING [MMADR+0x20C8] + + Or(ShiftLeft(Derefof(Index(CDCT, \_SB.PCI0.GFX0.MCHK.DCFE)), 21),PARM, PARM) + + Store(1, GESF) // Set the modified settings flag + Return(SUCC) + } + + // Spread spectrum clocks: Sub-function 10 + + If (LEqual(GESF, 10)) + { + + Store(0, PARM) // Assume SSC is disabled + + If(ISSC) + { + Or(PARM, 3, PARM) // If SSC enabled, return SSC1+Enabled + } + + Store(0, GESF) // Set the modified settings flag + Return(SUCC) // Success + } + + + // A call to a reserved "Get BIOS data" function was received. + + Store(Zero, GESF) // Clear the exit parameter + Return(CRIT) // Reserved, "Critical failure" +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOMOBF.ASL b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOMOBF.ASL new file mode 100644 index 0000000000..927e43d585 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOMOBF.ASL @@ -0,0 +1,491 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + IgdOMOBF.ASL + +Abstract: + + IGD OpRegion/Software SCI Reference Code for the Baytrail Family. + This file contains ASL code with the purpose of handling events + i.e. hotkeys and other system interrupts. + +--*/ + + +// Notes: +// 1. The following routines are to be called from the appropriate event +// handlers. +// 2. This code cannot comprehend the exact implementation in the OEM's BIOS. +// Therefore, an OEM must call these methods from the existing event +// handler infrastructure. Details on when/why to call each method is +// included in the method header under the "usage" section. + + +/************************************************************************; +;* ACPI Notification Methods +;************************************************************************/ + + +/************************************************************************; +;* +;* Name: PDRD +;* +;* Description: Check if the graphics driver is ready to process +;* notifications and video extensions. +;* +;* Usage: This method is to be called prior to performing any +;* notifications or handling video extensions. +;* Ex: If (PDRD()) {Return (FAIL)} +;* +;* Input: None +;* +;* Output: None +;* +;* References: DRDY (Driver ready status), ASLP (Driver recommended +;* sleep timeout value). +;* +;************************************************************************/ + +Method(PDRD) +{ + If(LNot(DRDY)) + { + + // Sleep for ASLP milliseconds if the driver is not ready. + + Sleep(ASLP) + } + + // If DRDY is clear, the driver is not ready. If the return value is + // !=0, do not perform any notifications or video extension handling. + + Return(LNot(DRDY)) +} + + +/************************************************************************; +;* +;* Name: PSTS +;* +;* Description: Check if the graphics driver has completed the previous +;* "notify" command. +;* +;* Usage: This method is called before every "notify" command. A +;* "notify" should only be set if the driver has completed the +;* previous command. Else, ignore the event and exit the parent +;* method. +;* Ex: If (PSTS()) {Return (FAIL)} +;* +;* Input: None +;* +;* Output: None +;* +;* References: CSTS (Notification status), ASLP (Driver recommended sleep +;* timeout value). +;* +;************************************************************************/ + +Method(PSTS) +{ + If(LGreater(CSTS, 2)) + { + // Sleep for ASLP milliseconds if the status is not "success, + // failure, or pending" + // + Sleep(ASLP) + } + + Return(LEqual(CSTS, 3)) // Return True if still Dispatched +} + + +/************************************************************************; +;* +;* Name: GNOT +;* +;* Description: Call the appropriate methods to query the graphics driver +;* status. If all methods return success, do a notification of +;* the graphics device. +;* +;* Usage: This method is to be called when a graphics device +;* notification is required (display switch hotkey, etc). +;* +;* Input: Arg0 = Current event type: +;* 1 = display switch +;* 2 = lid +;* 3 = dock +;* Arg1 = Notification type: +;* 0 = Re-enumeration +;* 0x80 = Display switch +;* +;* Output: Returns 0 = success, 1 = failure +;* +;* References: PDRD and PSTS methods. OSYS (OS version) +;* +;************************************************************************/ + +Method(GNOT, 2) +{ + // Check for 1. Driver loaded, 2. Driver ready. + // If any of these cases is not met, skip this event and return failure. + // + If(PDRD()) + { + Return(0x1) // Return failure if driver not loaded. + } + + Store(Arg0, CEVT) // Set up the current event value + Store(3, CSTS) // CSTS=BIOS dispatched an event + + If(LAnd(LEqual(CHPD, 0), LEqual(Arg1, 0))) // Do not re-enum if driver supports hotplug + { + If(LOr(LGreater(OSYS, 2000), LLess(OSYS, 2006))) + { + // + // WINXP requires that the entire PCI Bridge be re-enumerated. + // + Notify(\_SB.PCI0, Arg1) + } + Else + { + // + // Re-enumerate the Graphics Device for non-XP operating systems. + // + Notify(\_SB.PCI0.GFX0, Arg1) + } + } + + Notify(\_SB.PCI0.GFX0,0x80) + + + Return(0x0) // Return success +} + + +/************************************************************************; +;* +;* Name: GHDS +;* +;* Description: Handle a hotkey display switching event (performs a +;* Notify(GFX0, 0). +;* +;* Usage: This method must be called when a hotkey event occurs and the +;* purpose of that hotkey is to do a display switch. +;* +;* Input: Arg0 = Toggle table number. +;* +;* Output: Returns 0 = success, 1 = failure. +;* CEVT and TIDX are indirect outputs. +;* +;* References: TIDX, GNOT +;* +;************************************************************************/ + +Method(GHDS, 1) +{ + Store(Arg0, TIDX) // Store the table number + + // Call GNOT for CEVT = 1 = hotkey, notify value = 0 + + Return(GNOT(1, 0)) // Return stats from GNOT +} + + +/************************************************************************; +;* +;* Name: GLID +;* +;* Description: Handle a lid event (performs the Notify(GFX0, 0), but not the +;* lid notify). +;* +;* Usage: This method must be called when a lid event occurs. A +;* Notify(LID0, 0x80) must follow the call to this method. +;* +;* Input: Arg0 = Lid state: +;* 0 = All closed +;* 1 = internal LFP lid open +;* 2 = external lid open +;* 3 = both external and internal open +;* +;* Output: Returns 0=success, 1=failure. +;* CLID and CEVT are indirect outputs. +;* +;* References: CLID, GNOT +;* +;************************************************************************/ + +Method(GLID, 1) +{ + Store(Arg0, CLID) // Store the current lid state + + // Call GNOT for CEVT=2=Lid, notify value = 0 + + Return(GNOT(2, 0)) // Return stats from GNOT +} + + +/************************************************************************; +;* +;* Name: GDCK +;* +;* Description: Handle a docking event by updating the current docking status +;* and doing a notification. +;* +;* Usage: This method must be called when a docking event occurs. +;* +;* Input: Arg0 = Docking state: +;* 0 = Undocked +;* 1 = Docked +;* +;* Output: Returns 0=success, 1=failure. +;* CDCK and CEVT are indirect outputs. +;* +;* References: CDCK, GNOT +;* +;************************************************************************/ + +Method(GDCK, 1) +{ + Store(Arg0, CDCK) // Store the current dock state + + // Call GNOT for CEVT=4=Dock, notify value = 0 + + Return(GNOT(4, 0)) // Return stats from GNOT +} + + +/************************************************************************; +;* ASLE Interrupt Methods +;************************************************************************/ + + +/************************************************************************; +;* +;* Name: PARD +;* +;* Description: Check if the driver is ready to handle ASLE interrupts +;* generate by the system BIOS. +;* +;* Usage: This method must be called before generating each ASLE +;* interrupt. +;* +;* Input: None +;* +;* Output: Returns 0 = success, 1 = failure. +;* +;* References: ARDY (Driver readiness), ASLP (Driver recommended sleep +;* timeout value) +;* +;************************************************************************/ + +Method(PARD) +{ + If(LNot(ARDY)) + { + + // Sleep for ASLP milliseconds if the driver is not ready. + + Sleep(ASLP) + } + + // If ARDY is clear, the driver is not ready. If the return value is + // !=0, do not generate the ASLE interrupt. + + Return(LNot(ARDY)) +} + + +/************************************************************************; +;* +;* Name: AINT +;* +;* Description: Call the appropriate methods to generate an ASLE interrupt. +;* This process includes ensuring the graphics driver is ready +;* to process the interrupt, ensuring the driver supports the +;* interrupt of interest, and passing information about the event +;* to the graphics driver. +;* +;* Usage: This method must called to generate an ASLE interrupt. +;* +;* Input: Arg0 = ASLE command function code: +;* 0 = Set ALS illuminance +;* 1 = Set backlight brightness +;* 2 = Do Panel Fitting +;* Arg1 = If Arg0 = 0, current ALS reading: +;* 0 = Reading below sensor range +;* 1-0xFFFE = Current sensor reading +;* 0xFFFF = Reading above sensor range +;* Arg1 = If Arg0 = 1, requested backlight percentage +;* +;* Output: Returns 0 = success, 1 = failure +;* +;* References: PARD method. +;* +;************************************************************************/ + +Method(AINT, 2) +{ + + // Return failure if the requested feature is not supported by the + // driver. + + If(LNot(And(TCHE, ShiftLeft(1, Arg0)))) + { + Return(0x1) + } + + // Return failure if the driver is not ready to handle an ASLE + // interrupt. + + If(PARD()) + { + Return(0x1) + } + + // Evaluate the first argument (Panel fitting, backlight brightness, or ALS). + + If(LEqual(Arg0, 2)) // Arg0 = 2, so request a panel fitting mode change. + { + If(CPFM) // If current mode field is non-zero use it. + { + And(CPFM, 0x0F, Local0) // Create variables without reserved + And(EPFM, 0x0F, Local1) // or valid bits. + + If(LEqual(Local0, 1)) // If current mode is centered, + { + If(And(Local1, 6)) // and if stretched is enabled, + { + Store(6, PFIT) // request stretched. + } + Else // Otherwise, + { + If(And(Local1, 8)) // if aspect ratio is enabled, + { + Store(8, PFIT) // request aspect ratio. + } + Else // Only centered mode is enabled + { + Store(1, PFIT) // so request centered. (No change.) + } + } + } + If(LEqual(Local0, 6)) // If current mode is stretched, + { + If(And(Local1, 8)) // and if aspect ratio is enabled, + { + Store(8, PFIT) // request aspect ratio. + } + Else // Otherwise, + { + If(And(Local1, 1)) // if centered is enabled, + { + Store(1, PFIT) // request centered. + } + Else // Only stretched mode is enabled + { + Store(6, PFIT) // so request stretched. (No change.) + } + } + } + If(LEqual(Local0, 8)) // If current mode is aspect ratio, + { + If(And(Local1, 1)) // and if centered is enabled, + { + Store(1, PFIT) // request centered. + } + Else // Otherwise, + { + If(And(Local1, 6)) // if stretched is enabled, + { + Store(6, PFIT) // request stretched. + } + Else // Only aspect ratio mode is enabled + { + Store(8, PFIT) // so request aspect ratio. (No change.) + } + } + } + } + + // The following code for panel fitting (within the Else condition) is retained for backward compatiblity. + + Else // If CFPM field is zero use PFIT and toggle the + { + Xor(PFIT,7,PFIT) // mode setting between stretched and centered only. + } + + Or(PFIT,0x80000000,PFIT) // Set the valid bit for all cases. + + Store(4, ASLC) // Store "Panel fitting event" to ASLC[31:1] + } + Else + { + If(LEqual(Arg0, 1)) // Arg0=1, so set the backlight brightness. + { + Store(Divide(Multiply(Arg1, 255), 100), BCLP) // Convert from percent to 0-255. + + Or(BCLP, 0x80000000, BCLP) // Set the valid bit. + + Store(2, ASLC) // Store "Backlight control event" to ASLC[31:1] + } + Else + { + If(LEqual(Arg0, 0)) // Arg0=0, so set the ALS illuminace + { + Store(Arg1, ALSI) + + Store(1, ASLC) // Store "ALS event" to ASLC[31:1] + } + Else + { + Return(0x1) // Unsupported function + } + } + } + + Store(0x01, ASLE) // Generate ASLE interrupt + Return(0x0) // Return success +} + + +/************************************************************************; +;* +;* Name: SCIP +;* +;* Description: Checks the presence of the OpRegion and SCI +;* +;* Usage: This method is called before other OpRegion methods. The +;* former "GSMI True/False is not always valid. This method +;* checks if the OpRegion Version is non-zero and if non-zero, +;* (present and readable) then checks the GSMI flag. +;* +;* Input: None +;* +;* Output: Boolean True = SCI present. +;* +;* References: None +;* +;************************************************************************/ + +Method(SCIP) +{ + If(LNotEqual(OVER,0)) // If OpRegion Version not 0. + { + Return(LNot(GSMI)) // Return True if SCI. + } + + Return(0) // Else Return False. +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOSBCB.ASL b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOSBCB.ASL new file mode 100644 index 0000000000..418329dce0 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOSBCB.ASL @@ -0,0 +1,280 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + IgdOSBCB.ASL + +Abstract: + + IGD OpRegion/Software SCI Reference Code for the Baytrail Family. + This file contains the system BIOS call back functionality for the + OpRegion/Software SCI mechanism. + +--*/ + + +Method (SBCB, 0, Serialized) +{ + + // Supported Callbacks: Sub-function 0 + + If (LEqual(GESF, 0x0)) + { + + // An OEM may support the driver->SBIOS status callbacks, but + // the supported callbacks value must be modified. The code that is + // executed upon reception of the callbacks must be also be updated + // to perform the desired functionality. + + Store(0x00000000, PARM) // No callbacks supported + + If(LEqual(PFLV,FMBL)) + { + Store(0x000F87FD, PARM) // Mobile + } + If(LEqual(PFLV,FDTP)) + { + Store(0x000F87BD, PARM) // Desktop + } + + Store(Zero, GESF) // Clear the exit parameter + Return(SUCC) // "Success" + } + + // BIOS POST Completion: Sub-function 1 + + If (LEqual(GESF, 1)) + { + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Not supported, but no failure + } + + // Pre-Hires Set Mode: Sub-function 3 + + If (LEqual(GESF, 3)) + { + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Not supported, but no failure + } + + // Post-Hires Set Mode: Sub-function 4 + + If (LEqual(GESF, 4)) + { + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Not supported, but no failure + } + + // Display Switch: Sub-function 5 + + If (LEqual(GESF, 5)) + { + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Not supported, but no failure + } + + // Set TV format: Sub-function 6 + + If (LEqual(GESF, 6)) + { + + // If implemented, the input values must be saved into + // non-volatile storage for parsing during the next boot. The + // following Sample code is Intel validated implementation. + + Store(And(PARM, 0x0F), ITVF) + Store(ShiftRight(And(PARM, 0xF0), 4), ITVM) + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) + } + + // Adapter Power State: Sub-function 7 + + If (LEqual(GESF, 7)) + { + + // Upon notification from driver that the Adapter Power State = D0, + // check if previous lid event failed. If it did, retry the lid + // event here. + If(LEqual(PARM, 0)) + { + Store(CLID, Local0) + If(And(0x80000000,Local0)) + { + And(CLID, 0x0000000F, CLID) + GLID(CLID) + } + } + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Not supported, but no failure + } + + // Display Power State: Sub-function 8 + + If (LEqual(GESF, 8)) + { + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Not supported, but no failure + } + + // Set Boot Display: Sub-function 9 + + If (LEqual(GESF, 9)) + { + + // An OEM may elect to implement this method. In that case, + // the input values must be saved into non-volatile storage for + // parsing during the next boot. The following Sample code is Intel + // validated implementation. + + And(PARM, 0xFF, IBTT) // Save the boot display to NVS + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Reserved, "Critical failure" + } + + // Set Panel Details: Sub-function 10 (0Ah) + + If (LEqual(GESF, 10)) + { + + // An OEM may elect to implement this method. In that case, + // the input values must be saved into non-volatile storage for + // parsing during the next boot. The following Sample code is Intel + // validated implementation. + + // Set the panel-related NVRAM variables based the input from the driver. + + And(PARM, 0xFF, IPSC) + + // Change panel type if a change is requested by the driver (Change if + // panel type input is non-zero). Zero=No change requested. + + If(And(ShiftRight(PARM, 8), 0xFF)) + { + And(ShiftRight(PARM, 8), 0xFF, IPAT) + Decrement(IPAT) // 0 = no change, so fit to CMOS map + } + And(ShiftRight(PARM, 18), 0x3, IBLC) + And(ShiftRight(PARM, 20), 0x7, IBIA) + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Success + } + + // Set Internal Graphics: Sub-function 11 (0Bh) + + If (LEqual(GESF, 11)) + { + + // An OEM may elect to implement this method. In that case, + // the input values must be saved into non-volatile storage for + // parsing during the next boot. The following Sample code is Intel + // validated implementation. + + And(ShiftRight(PARM, 1), 1, IF1E) // Program the function 1 option + + // Fixed memory/DVMT memory + + And(ShiftRight(PARM, 17), 0xF, IDMS) // Program DVMT/fixed memory size + + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Success + } + + // Post-Hires to DOS FS: Sub-function 16 (10h) + + If (LEqual(GESF, 16)) + { + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Not supported, but no failure + } + + // APM Complete: Sub-function 17 (11h) + + If (LEqual(GESF, 17)) + { + + Store(ShiftLeft(LIDS, 8), PARM) // Report the lid state + Add(PARM, 0x100, PARM) // Adjust the lid state, 0 = Unknown + + Store(Zero, GESF) // Clear the exit parameter + Return(SUCC) // Not supported, but no failure + } + + // Set Spread Spectrum Clocks: Sub-function 18 (12h) + + If (LEqual(GESF, 18)) + { + + // An OEM may elect to implement this method. In that case, + // the input values must be saved into non-volatile storage for + // parsing during the next boot. The following Sample code is Intel + // validated implementation. + + If(And(PARM, 1)) + { + If(LEqual(ShiftRight(PARM, 1), 1)) + { + Store(1, ISSC) // Enable HW SSC, only for clock 1 + } + Else + { + Store(Zero, GESF) + Return(CRIT) // Failure, as the SSC clock must be 1 + } + } + Else + { + Store(0, ISSC) // Disable SSC + } + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Success + } + + // Post VBE/PM Callback: Sub-function 19 (13h) + + If (LEqual(GESF, 19)) + { + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Not supported, but no failure + } + + // Set PAVP Data: Sub-function 20 (14h) + + If (LEqual(GESF, 20)) + { + And(PARM, 0xF, PAVP) // Store PAVP info + Store(Zero, GESF) // Clear the exit parameter + Store(Zero, PARM) + Return(SUCC) // Success + } + + // A call to a reserved "System BIOS callbacks" function was received + + Store(Zero, GESF) // Clear the exit parameter + Return(SUCC) // Reserved, "Critical failure" +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOpRn.ASL b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOpRn.ASL new file mode 100644 index 0000000000..65190af2c5 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IgdOpRn.ASL @@ -0,0 +1,305 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + IgdOpRn.ASL + +Abstract: + + IGD OpRegion/Software SCI Reference Code for the Baytrail Family. + This file contains the interrupt handler code for the Integrated + Graphics Device (IGD) OpRegion/Software SCI mechanism. + +--*/ + + +//NOTES: +// +// (1) The code contained in this file inherits the scope in which it +// was included. So BIOS developers must be sure to include this +// file in the scope associated with the graphics device +// (ex. \_SB.PCI0.GFX0). +// (2) Create a _L06 method under the GPE scope to handle the event +// generated by the graphics driver. The _L06 method must call +// the GSCI method in this file. +// (3) The MCHP operation region assumes that _ADR and _BBN names +// corresponding to bus 0, device0, function 0 have been declared +// under the PCI0 scope. +// (4) Before the first execution of the GSCI method, the base address +// of the GMCH SCI OpRegion must be programmed where the driver can +// access it. A 32bit scratch register at 0xFC in the IGD PCI +// configuration space (B0/D2/F0/R0FCh) is used for this purpose. + +// Define an OperationRegion to cover the GMCH PCI configuration space as +// described in the IGD OpRegion specificiation. + +// Define an OperationRegion to cover the IGD PCI configuration space as +// described in the IGD OpRegion specificiation. + +OperationRegion(IGDP, PCI_Config,0x00,0x100) +Field(IGDP, AnyAcc, NoLock, Preserve) +{ + Offset(0x10), // GTTMMADR + MADR, 32, + Offset(0x50), // GMCH Graphics Control Register + , 1, + GIVD, 1, // IGD VGA disable bit + , 1, + GUMA, 5, // Stolen memory size + , 8, + Offset(0x54), + , 4, + GMFN, 1, // Gfx function 1 enable + , 27, + Offset(0x5C), // Stolen Memory Base Address + GSTM, 32, + Offset(0xE0), // Reg 0xE8, SWSCI control register + GSSE, 1, // Graphics SCI event (1=event pending) + GSSB, 14, // Graphics SCI scratchpad bits + GSES, 1, // Graphics event select (1=SCI) + Offset(0xE4), + ASLE, 8, // Reg 0xE4, ASLE interrupt register + , 24, // Only use first byte of ASLE reg + Offset(0xFC), + ASLS, 32, // Reg 0xFC, Address of the IGD OpRegion +} + +Method (MCHK, 0, Serialized) +{ + + If (LNotEqual (MADR, 0xFFFFFFFF)) + { + OperationRegion(IGMM,SystemMemory,MADR,0x3000) + Field(IGMM,AnyAcc, NoLock, Preserve) + { + Offset(0X20C8), + , 4, + DCFE, 4, // DISPLAY_CLOCK_FREQUENCY_ENCODING + } + } +} + + +// Define an OperationRegion to cover the IGD OpRegion layout. + +OperationRegion(IGDM, SystemMemory, ASLB, 0x2000) +Field(IGDM, AnyAcc, NoLock, Preserve) +{ + + // OpRegion Header + + SIGN, 128, // Signature-"IntelGraphicsMem" + SIZE, 32, // OpRegion Size + OVER, 32, // OpRegion Version + SVER, 256, // System BIOS Version + VVER, 128, // VBIOS Version + GVER, 128, // Driver version + MBOX, 32, // Mailboxes supported + DMOD, 32, // Driver Model + PCON, 32, // 96, Platform Configuration + + // OpRegion Mailbox 1 (Public ACPI Methods) + // Note: Mailbox 1 is normally reserved for desktop platforms. + + Offset(0x100), + DRDY, 32, // Driver readiness (ACPI notification) + CSTS, 32, // Notification status + CEVT, 32, // Current event + Offset(0x120), + DIDL, 32, // Supported display device ID list + DDL2, 32, // Allows for 8 devices + DDL3, 32, + DDL4, 32, + DDL5, 32, + DDL6, 32, + DDL7, 32, + DDL8, 32, + CPDL, 32, // Currently present display list + CPL2, 32, // Allows for 8 devices + CPL3, 32, + CPL4, 32, + CPL5, 32, + CPL6, 32, + CPL7, 32, + CPL8, 32, + CAD1, 32, // Currently active display list + CAL2, 32, // Allows for 8 devices + CAL3, 32, + CAL4, 32, + CAL5, 32, + CAL6, 32, + CAL7, 32, + CAL8, 32, + NADL, 32, // Next active display list + NDL2, 32, // Allows for 8 devices + NDL3, 32, + NDL4, 32, + NDL5, 32, + NDL6, 32, + NDL7, 32, + NDL8, 32, + ASLP, 32, // ASL sleep timeout + TIDX, 32, // Toggle table index + CHPD, 32, // Current hot plug enable indicator + CLID, 32, // Current lid state indicator + CDCK, 32, // Current docking state indicator + SXSW, 32, // Display switch notify on resume + EVTS, 32, // Events supported by ASL (diag only) + CNOT, 32, // Current OS notifications (diag only) + NRDY, 32, + + // OpRegion Mailbox 2 (Software SCI Interface) + + Offset(0x200), // SCIC + SCIE, 1, // SCI entry bit (1=call unserviced) + GEFC, 4, // Entry function code + GXFC, 3, // Exit result + GESF, 8, // Entry/exit sub-function/parameter + , 16, // SCIC[31:16] reserved + Offset(0x204), // PARM + PARM, 32, // PARM register (extra parameters) + DSLP, 32, // Driver sleep time out + + // OpRegion Mailbox 3 (BIOS to Driver Notification) + // Note: Mailbox 3 is normally reserved for desktop platforms. + + Offset(0x300), + ARDY, 32, // Driver readiness (power conservation) + ASLC, 32, // ASLE interrupt command/status + TCHE, 32, // Technology enabled indicator + ALSI, 32, // Current ALS illuminance reading + BCLP, 32, // Backlight brightness + PFIT, 32, // Panel fitting state or request + CBLV, 32, // Current brightness level + BCLM, 320, // Backlight brightness level duty cycle mapping table + CPFM, 32, // Current panel fitting mode + EPFM, 32, // Enabled panel fitting modes + PLUT, 592, // Optional. 74-byte Panel LUT Table + PFMB, 32, // Optional. PWM Frequency and Minimum Brightness + CCDV, 32, // Optional. Gamma, Brightness, Contrast values. + PCFT, 32, // Optional. Power Conservation Features + + Offset(0x3B6), + STAT, 32, // Status register + + // OpRegion Mailbox 4 (VBT) + + Offset(0x400), + GVD1, 0xC000, // 6K bytes maximum VBT image + + // OpRegion Mailbox 5 (BIOS to Driver Notification Extension) + + Offset(0x1C00), + PHED, 32, // Panel Header + BDDC, 2048, // Panel EDID (Max 256 bytes) + +} + + + +// Convert boot display type into a port mask. + +Name (DBTB, Package() +{ + 0x0000, // Automatic + 0x0007, // Port-0 : Integrated CRT + 0x0038, // Port-1 : DVO-A, or Integrated LVDS + 0x01C0, // Port-2 : SDVO-B, or SDVO-B/C + 0x0E00, // Port-3 : SDVO-C + 0x003F, // [CRT + DVO-A / Integrated LVDS] + 0x01C7, // [CRT + SDVO-B] or [CRT + SDVO-B/C] + 0x0E07, // [CRT + SDVO-C] + 0x01F8, // [DVO-A / Integrated LVDS + SDVO-B] + 0x0E38, // [DVO-A / Integrated LVDS + SDVO-C] + 0x0FC0, // [SDVO-B + SDVO-C] + 0x0000, // Reserved + 0x0000, // Reserved + 0x0000, // Reserved + 0x0000, // Reserved + 0x0000, // Reserved + 0x7000, // Port-4: Integrated TV + 0x7007, // [Integrated TV + CRT] + 0x7038, // [Integrated TV + LVDS] + 0x71C0, // [Integrated TV + DVOB] + 0x7E00 // [Integrated TV + DVOC] +}) + +// Core display clock value table. + +Name (CDCT, Package() +{ + Package() {160}, + Package() {200}, + Package() {267}, + Package() {320}, + Package() {356}, + Package() {400}, +}) + +// Defined exit result values: + +Name (SUCC, 1) // Exit result: Success +Name (NVLD, 2) // Exit result: Invalid parameter +Name (CRIT, 4) // Exit result: Critical failure +Name (NCRT, 6) // Exit result: Non-critical failure + + +/************************************************************************; +;* +;* Name: GSCI +;* +;* Description: Handles an SCI generated by the graphics driver. The +;* PARM and SCIC input fields are parsed to determine the +;* functionality requested by the driver. GBDA or SBCB +;* is called based on the input data in SCIC. +;* +;* Usage: The method must be called in response to a GPE 06 event +;* which will be generated by the graphics driver. +;* Ex: Method(\_GPE._L06) {Return(\_SB.PCI0.GFX0.GSCI())} +;* +;* Input: PARM and SCIC are indirect inputs +;* +;* Output: PARM and SIC are indirect outputs +;* +;* References: GBDA (Get BIOS Data method), SBCB (System BIOS Callback +;* method) +;* +;************************************************************************/ + +Method (GSCI, 0, Serialized) +{ + Include("IgdOGBDA.ASL") // "Get BIOS Data" Functions + Include("IgdOSBCB.ASL") // "System BIOS CallBacks" + + If (LEqual(GEFC, 4)) + { + Store(GBDA(), GXFC) // Process Get BIOS Data functions + } + + If (LEqual(GEFC, 6)) + { + Store(SBCB(), GXFC) // Process BIOS Callback functions + } + + Store(0, GEFC) // Wipe out the entry function code + Store(1, SCIS) // Clear the GUNIT SCI status bit in PCH ACPI I/O space. + Store(0, GSSE) // Clear the SCI generation bit in PCI space. + Store(0, SCIE) // Clr SCI serviced bit to signal completion + + Return(Zero) +} + +// Include MOBLFEAT.ASL for mobile systems only. Remove for desktop. +Include("IgdOMOBF.ASL") // IGD SCI mobile features diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IoTVirtualDevice.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IoTVirtualDevice.asl new file mode 100644 index 0000000000..ef1383b9c1 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/IoTVirtualDevice.asl @@ -0,0 +1,177 @@ +/** @file +Copyright (c) 2014, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +Device(IOTD) { + Name(_HID, "MSFT8000") + Name(_CID, "MSFT8000") + + Name(_CRS, ResourceTemplate() { + // Index 0 + SPISerialBus( // Pin 5, 7, 9 , 11 of JP1 for SIO_SPI + 1, // Device selection + PolarityLow, // Device selection polarity + FourWireMode, // wiremode + 8, // databit len + ControllerInitiated, // slave mode + 8000000, // Connection speed + ClockPolarityLow, // Clock polarity + ClockPhaseSecond, // clock phase + "\\_SB.SPI1", // ResourceSource: SPI bus controller name + 0, // ResourceSourceIndex + ResourceConsumer, // Resource usage + JSPI, // DescriptorName: creates name for offset of resource descriptor + ) // Vendor Data + + // Index 1 + I2CSerialBus( // Pin 13, 15 of JP1, for SIO_I2C5 (signal) + 0x00, // SlaveAddress: bus address (TBD) + , // SlaveMode: default to ControllerInitiated + 400000, // ConnectionSpeed: in Hz + , // Addressing Mode: default to 7 bit + "\\_SB.I2C6", // ResourceSource: I2C bus controller name (For MinnowBoard Max, hardware I2C5(0-based) is reported as ACPI I2C6(1-based)) + , + , + JI2C, // Descriptor Name: creates name for offset of resource descriptor + ) // VendorData + + // Index 2 + UARTSerialBus( // Pin 17, 19 of JP1, for SIO_UART2 + 115200, // InitialBaudRate: in bits ber second + , // BitsPerByte: default to 8 bits + , // StopBits: Defaults to one bit + 0xfc, // LinesInUse: 8 1-bit flags to declare line enabled + , // IsBigEndian: default to LittleEndian + , // Parity: Defaults to no parity + , // FlowControl: Defaults to no flow control + 32, // ReceiveBufferSize + 32, // TransmitBufferSize + "\\_SB.URT2", // ResourceSource: UART bus controller name + , + , + UAR2, // DescriptorName: creates name for offset of resource descriptor + ) + + // Index 3 + GpioIo (Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.GPO2",) {0} // Pin 21 of JP1 (GPIO_S5[00]) + // Index 4 + GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO2",) {0} + + // Index 5 + GpioIo (Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.GPO2",) {1} // Pin 23 of JP1 (GPIO_S5[01]) + // Index 6 + GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO2",) {1} + + // Index 7 + GpioIo (Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.GPO2",) {2} // Pin 25 of JP1 (GPIO_S5[02]) + // Index 8 + GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO2",) {2} + + // Index 9 + UARTSerialBus( // Pin 6, 8, 10, 12 of JP1, for SIO_UART1 + 115200, // InitialBaudRate: in bits ber second + , // BitsPerByte: default to 8 bits + , // StopBits: Defaults to one bit + 0xfc, // LinesInUse: 8 1-bit flags to declare line enabled + , // IsBigEndian: default to LittleEndian + , // Parity: Defaults to no parity + FlowControlHardware, // FlowControl: Defaults to no flow control + 32, // ReceiveBufferSize + 32, // TransmitBufferSize + "\\_SB.URT1", // ResourceSource: UART bus controller name + , + , + UAR1, // DescriptorName: creates name for offset of resource descriptor + ) + + // Index 10 + GpioIo (Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {62} // Pin 14 of JP1 (GPIO_SC[62]) + // Index 11 + GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {62} + + // Index 12 + GpioIo (Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {63} // Pin 16 of JP1 (GPIO_SC[63]) + // Index 13 + GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {63} + + // Index 14 + GpioIo (Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {65} // Pin 18 of JP1 (GPIO_SC[65]) + // Index 15 + GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {65} + + // Index 16 + GpioIo (Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {64} // Pin 20 of JP1 (GPIO_SC[64]) + // Index 17 + GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {64} + + // Index 18 + GpioIo (Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {94} // Pin 22 of JP1 (GPIO_SC[94]) + // Index 19 + GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {94} + + // Index 20 + GpioIo (Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {95} // Pin 24 of JP1 (GPIO_SC[95]) + // Index 21 + GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {95} + + // Index 22 + GpioIo (Shared, PullDefault, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {54} // Pin 26 of JP1 (GPIO_SC[54]) + // Index 23 + GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {54} + }) + + Name(_DSD, Package() { + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + Package(1) { // Just one Property for IOT (at this time) + Package(2) { //The “symbolic-identifiers” property + "symbolic-identifiers", + Package() { //Contains all the pairs + 0, "SPI0", + 1, "I2C5", + 2, "UART2", + 3, 21, // Pin 21 of JP1 (GPIO_S5[00]) + 4, 21, // Pin 21 for separate resource. + 5, 23, // Pin 23 of JP1 (GPIO_S5[01]) + 6, 23, + 7, 25, // Pin 25 of JP1 (GPIO_S5[02]) + 8, 25, + 9, "UART1", + 10, 14, // Pin 14 of JP1 (GPIO_SC[62]) + 11, 14, + 12, 16, // Pin 16 of JP1 (GPIO_SC[63]) + 13, 16, + 14, 18, // Pin 18 of JP1 (GPIO_SC[65]) + 15, 18, + 16, 20, // Pin 20 of JP1 (GPIO_SC[64]) + 17, 20, + 18, 22, // Pin 22 of JP1 (GPIO_SC[94]) + 19, 22, + 20, 24, // Pin 24 of JP1 (GPIO_SC[95]) + 21, 24, + 22, 26, // Pin 26 of JP1 (GPIO_SC[54]) + 23, 26 + } + } + } + }) + + Method(_STA,0,Serialized) { + + // + // Only report IoT virtual device when all pins' configuration follows MSFT's datasheet. + // + If (LEqual(IOT, 1)) { + Return (0xF) + } + + Return (0x0) + } +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/LPC_DEV.ASL b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/LPC_DEV.ASL new file mode 100644 index 0000000000..31b4050a3a --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/LPC_DEV.ASL @@ -0,0 +1,157 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + +Device(FWHD) // Firmware Hub Device +{ + Name(_HID,EISAID("INT0800")) + + Name(_CRS,ResourceTemplate() + { + Memory32Fixed(ReadOnly,0xFF000000,0x1000000) + }) +} + +Device(IPIC) // 8259 PIC +{ + Name(_HID,EISAID("PNP0000")) + + Name(_CRS,ResourceTemplate() + { + IO(Decode16,0x20,0x20,0x01,0x02) + IO(Decode16,0x24,0x24,0x01,0x02) + IO(Decode16,0x28,0x28,0x01,0x02) + IO(Decode16,0x2C,0x2C,0x01,0x02) + IO(Decode16,0x30,0x30,0x01,0x02) + IO(Decode16,0x34,0x34,0x01,0x02) + IO(Decode16,0x38,0x38,0x01,0x02) + IO(Decode16,0x3C,0x3C,0x01,0x02) + IO(Decode16,0xA0,0xA0,0x01,0x02) + IO(Decode16,0xA4,0xA4,0x01,0x02) + IO(Decode16,0xA8,0xA8,0x01,0x02) + IO(Decode16,0xAC,0xAC,0x01,0x02) + IO(Decode16,0xB0,0xB0,0x01,0x02) + IO(Decode16,0xB4,0xB4,0x01,0x02) + IO(Decode16,0xB8,0xB8,0x01,0x02) + IO(Decode16,0xBC,0xBC,0x01,0x02) + IO(Decode16,0x4D0,0x4D0,0x01,0x02) + IRQNoFlags() {2} + }) +} + +Device(LDRC) // LPC Device Resource Consumption +{ + Name(_HID,EISAID("PNP0C02")) + + Name(_UID,2) + + Name(_CRS,ResourceTemplate() + { + IO(Decode16,0x4E,0x4E,0x1,0x02) // LPC Slot Access. + IO(Decode16,0x61,0x61,0x1,0x1) // NMI Status. + IO(Decode16,0x63,0x63,0x1,0x1) // Processor I/F. + IO(Decode16,0x65,0x65,0x1,0x1) // Processor I/F. + IO(Decode16,0x67,0x67,0x1,0x1) // Processor I/F. + IO(Decode16,0x70,0x70,0x1,0x1) // NMI Enable. + IO(Decode16,0x80,0x80,0x1,0x10) // Postcode. + IO(Decode16,0x92,0x92,0x1,0x1) // Processor I/F. + IO(Decode16,0xB2,0xB2,0x01,0x02) // Software SMI. + IO(Decode16,0x680,0x680,0x1,0x20) // 32 Byte I/O. + IO(Decode16,0x400,0x400,0x1,0x80) // ACPI Base. + IO(Decode16,0x500,0x500,0x1,0xFF) // GPIO Base. + }) +} + +Device(TIMR) // 8254 Timer +{ + Name(_HID,EISAID("PNP0100")) + + Name(_CRS,ResourceTemplate() + { + IO(Decode16,0x40,0x40,0x01,0x04) + IO(Decode16,0x50,0x50,0x10,0x04) + IRQNoFlags() {0} + }) +} + +Device(IUR3) // Internal UART +{ + Name(_HID, EISAID("PNP0501")) + + Name(_UID,1) + + // Status Method for internal UART + + Method(_STA,0,Serialized) + { + // Only report resources to the OS if internal UART is + // not set to Disabled in BIOS Setup. + + If(LEqual(USEL,0)) + { + If(LEqual(PU1E,1)) + { + Store(1,UI3E) // Enable IRQ3 for UART + Store(1,UI4E) // Enable IRQ4 for UART + Store(1,C1EN) // Enable UART + Return(0x000F) + } + } + + Return(0x0000) + } + + // Disable Method for internal UART + + Method(_DIS,0,Serialized) + { + Store(0,UI3E) + Store(0,UI4E) + Store(0,C1EN) + } + + // Current Resource Setting Method for internal UART + + Method(_CRS,0,Serialized) + { + // Create the Buffer that stores the Resources to + // be returned. + + Name(BUF0,ResourceTemplate() + { + IO(Decode16,0x03F8,0x03F8,0x01,0x08) + IRQNoFlags() {3} + }) + + Name(BUF1,ResourceTemplate() + { + IO(Decode16,0x03F8,0x03F8,0x01,0x08) + IRQNoFlags() {4} + }) + + If (LLessEqual(SRID, 0x04)) + { + Return(BUF0) + } Else + { + Return(BUF1) + } + } +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/LpcB.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/LpcB.asl new file mode 100644 index 0000000000..afa6a53a4d --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/LpcB.asl @@ -0,0 +1,65 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + + +// LPC Bridge - Device 31, Function 0 +// Define the needed LPC registers used by ASL. + +scope(\_SB) +{ + OperationRegion(ILBR, SystemMemory, \IBAS, 0x8C) + Field(ILBR, AnyAcc, NoLock, Preserve) + { + Offset(0x08), // 0x08 + PARC, 8, + PBRC, 8, + PCRC, 8, + PDRC, 8, + PERC, 8, + PFRC, 8, + PGRC, 8, + PHRC, 8, + Offset(0x88), // 0x88 + , 3, + UI3E, 1, + UI4E, 1 + } + + Include ("98_LINK.ASL") +} + +OperationRegion(LPC0, PCI_Config, 0x00, 0xC0) +Field(LPC0, AnyAcc, NoLock, Preserve) +{ + Offset(0x08), // 0x08 + SRID, 8, // Revision ID + Offset(0x080), // 0x80 + C1EN, 1, // COM1 Enable + , 31 +} + + +Include ("LPC_DEV.ASL") + + + + + diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Lpit/Lpit.aslc b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Lpit/Lpit.aslc new file mode 100644 index 0000000000..ae81b2f4b1 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Lpit/Lpit.aslc @@ -0,0 +1,229 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +--*/ + +// +// Include files +// + +#include +#include + + + +// +// LPIT Definitions +// + +#define EFI_ACPI_LOW_POWER_IDLE_TABLE_REVISION 0x1 + +// +// Ensure proper structure formats +// +#pragma pack(1) + +typedef union _EFI_ACPI_LPI_STATE_FLAGS { + struct { + UINT32 Disabled :1; + UINT32 CounterUnavailable :1; + UINT32 Reserved :30; + }; + UINT32 AsUlong; +} EFI_ACPI_LPI_STATE_FLAGS, *PEFI_ACPI_LPI_STATE_FLAGS; + +// Only Mwait LPI here: + +typedef struct _EFI_ACPI_MWAIT_LPI_STATE_DESCRIPTOR { + UINT32 Type; // offset: 0 + UINT32 Length; // offset: 4 + UINT16 UniqueId; // offset: 8 + UINT8 Reserved[2]; // offset: 9 + EFI_ACPI_LPI_STATE_FLAGS Flags; // offset: 12 + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE EntryTrigger; // offset: 16 + UINT32 Residency; // offset: 28 + UINT32 Latency; // offset: 32 + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE ResidencyCounter; // offset: 36 + UINT64 ResidencyCounterFrequency; //offset: 48 +} EFI_ACPI_MWAIT_LPI_STATE_DESCRIPTOR; + + +// +// Defines for LPIT table, some are VLV specific +// + + +// signature "LPIT" +#define EFI_ACPI_LOW_POWER_IDLE_TABLE_SIGNATURE 0x5449504c + +#define EFI_ACPI_OEM_LPIT_REVISION 0x00000000 + +#define EFI_ACPI_LOW_POWER_IDLE_MWAIT_TYPE 0x0 +#define EFI_ACPI_LOW_POWER_IDLE_DEFAULT_FLAG 0x0 +#define EFI_ACPI_LOW_POWER_IDLE_RES_FREQ_8K 0x8000 // 32768 + +// +// LPI state count (4 on VLV: S0ir, S0i1, S0i2, S0i3) +// + +#define EFI_ACPI_VLV_LPI_STATE_COUNT 0x4 + +// +// LPI TRIGGER (HW C7 on VLV), +// TOFIX!!! +// +#define EFI_ACPI_VLV_LPI_TRIGGER {0x7F,0x1,0x2,0x0,0x64} + +// +// LPI residency counter (MMIO) +// +#define EFI_ACPI_VLV_LPI_RES_COUNTER0 {0x0,32,0x0,0x03,0xFED03080} +#define EFI_ACPI_VLV_LPI_RES_COUNTER1 {0x0,32,0x0,0x03,0xFED03084} +#define EFI_ACPI_VLV_LPI_RES_COUNTER2 {0x0,32,0x0,0x03,0xFED03088} +#define EFI_ACPI_VLV_LPI_RES_COUNTER3 {0x0,32,0x0,0x03,0xFED0308C} + +// +// LPI break-even residency in us - all match S0i3 residency +// Residency estimate: Latency x 3 +// +#define EFI_ACPI_VLV_LPI_MIN_RES0 15000 +#define EFI_ACPI_VLV_LPI_MIN_RES1 15000 +#define EFI_ACPI_VLV_LPI_MIN_RES2 15000 +#define EFI_ACPI_VLV_LPI_MIN_RES3 15000 + +// +// LPI latency in us - all match S0i3 latency +// +#define EFI_ACPI_VLV_LPI_LATENCY0 5000 +#define EFI_ACPI_VLV_LPI_LATENCY1 5000 +#define EFI_ACPI_VLV_LPI_LATENCY2 5000 +#define EFI_ACPI_VLV_LPI_LATENCY3 5000 + + +// +// LPI ID +// +#define EFI_ACPI_VLV_LPI_UNIQUE_ID0 0 +#define EFI_ACPI_VLV_LPI_UNIQUE_ID1 1 +#define EFI_ACPI_VLV_LPI_UNIQUE_ID2 2 +#define EFI_ACPI_VLV_LPI_UNIQUE_ID3 3 + +// +// LPI ACPI table header +// + + +typedef struct _EFI_ACPI_LOW_POWER_IDLE_TABLE { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_MWAIT_LPI_STATE_DESCRIPTOR LpiStates[EFI_ACPI_VLV_LPI_STATE_COUNT]; +} EFI_ACPI_LOW_POWER_IDLE_TABLE; + +#pragma pack() + +EFI_ACPI_LOW_POWER_IDLE_TABLE Lpit = { + + // + // Header + // + + + EFI_ACPI_LOW_POWER_IDLE_TABLE_SIGNATURE, + sizeof (EFI_ACPI_LOW_POWER_IDLE_TABLE), + EFI_ACPI_LOW_POWER_IDLE_TABLE_REVISION , + + // + // Checksum will be updated at runtime + // + 0x00, + + // + // It is expected that these values will be updated at runtime + // + ' ', ' ', ' ', ' ', ' ', ' ', + + 0, + EFI_ACPI_OEM_LPIT_REVISION, + 0, + 0, + + + + // + // Descriptor + // + { + { + EFI_ACPI_LOW_POWER_IDLE_MWAIT_TYPE, + sizeof(EFI_ACPI_MWAIT_LPI_STATE_DESCRIPTOR), + EFI_ACPI_VLV_LPI_UNIQUE_ID0, + {0,0}, + {EFI_ACPI_LOW_POWER_IDLE_DEFAULT_FLAG}, // Flags + EFI_ACPI_VLV_LPI_TRIGGER, //EntryTrigger + EFI_ACPI_VLV_LPI_MIN_RES0, //Residency + EFI_ACPI_VLV_LPI_LATENCY0, //Latency + EFI_ACPI_VLV_LPI_RES_COUNTER0, //ResidencyCounter + EFI_ACPI_LOW_POWER_IDLE_RES_FREQ_8K //Residency counter frequency + }, + { + EFI_ACPI_LOW_POWER_IDLE_MWAIT_TYPE, + sizeof(EFI_ACPI_MWAIT_LPI_STATE_DESCRIPTOR), + EFI_ACPI_VLV_LPI_UNIQUE_ID1, + {0,0}, + {EFI_ACPI_LOW_POWER_IDLE_DEFAULT_FLAG}, // Flags + EFI_ACPI_VLV_LPI_TRIGGER, //EntryTrigger + EFI_ACPI_VLV_LPI_MIN_RES1, //Residency + EFI_ACPI_VLV_LPI_LATENCY1, //Latency + EFI_ACPI_VLV_LPI_RES_COUNTER1, //ResidencyCounter + EFI_ACPI_LOW_POWER_IDLE_RES_FREQ_8K //Residency counter frequency + }, + { + EFI_ACPI_LOW_POWER_IDLE_MWAIT_TYPE, + sizeof(EFI_ACPI_MWAIT_LPI_STATE_DESCRIPTOR), + EFI_ACPI_VLV_LPI_UNIQUE_ID2, + {0,0}, + {EFI_ACPI_LOW_POWER_IDLE_DEFAULT_FLAG}, // Flags + EFI_ACPI_VLV_LPI_TRIGGER, //EntryTrigger + EFI_ACPI_VLV_LPI_MIN_RES2, //Residency + EFI_ACPI_VLV_LPI_LATENCY2, //Latency + EFI_ACPI_VLV_LPI_RES_COUNTER2, //ResidencyCounter + EFI_ACPI_LOW_POWER_IDLE_RES_FREQ_8K //Residency counter frequency + }, + { + EFI_ACPI_LOW_POWER_IDLE_MWAIT_TYPE, + sizeof(EFI_ACPI_MWAIT_LPI_STATE_DESCRIPTOR), + EFI_ACPI_VLV_LPI_UNIQUE_ID3, + {0,0}, + {EFI_ACPI_LOW_POWER_IDLE_DEFAULT_FLAG}, // Flags + EFI_ACPI_VLV_LPI_TRIGGER, //EntryTrigger + EFI_ACPI_VLV_LPI_MIN_RES3, //Residency + EFI_ACPI_VLV_LPI_LATENCY3, //Latency + EFI_ACPI_VLV_LPI_RES_COUNTER3, //ResidencyCounter + EFI_ACPI_LOW_POWER_IDLE_RES_FREQ_8K //Residency counter frequency + } + } + +}; + + +VOID* +ReferenceAcpiTable ( + VOID + ) +{ + // + // Reference the table being generated to prevent the optimizer from + // removing the data structure from the executable + // + return (VOID*)&Lpit; +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Madt/Madt.h b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Madt/Madt.h new file mode 100644 index 0000000000..7a01d6487f --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Madt/Madt.h @@ -0,0 +1,195 @@ +/*++ + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +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 Acpi1_0.h and + Acpi2_0.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 "AcpiTablePlatform.h" +#include +#include +#include +#include "Platform.h" + +// +// MADT Definitions +// +#define EFI_ACPI_OEM_MADT_REVISION 0x00000000 +// +// 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 EFI_ACPI_3_0_MULTIPLE_APIC_FLAGS (EFI_ACPI_3_0_PCAT_COMPAT) +#define EFI_ACPI_4_0_MULTIPLE_APIC_FLAGS (EFI_ACPI_4_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 MAX_CPU_NUM +#define EFI_ACPI_LOCAL_APIC_NMI_COUNT MAX_CPU_NUM +#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_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 + +// +// 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_ADDRESS_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; + +// +// ACPI 3.0 Table structure +// +typedef struct { + EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header; + +#if EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT > 0 // Type 0x00 + EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_STRUCTURE LocalApic[EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT]; +#endif + +#if EFI_ACPI_IO_APIC_COUNT > 0 // Type 0x01 + EFI_ACPI_3_0_IO_APIC_STRUCTURE IoApic[EFI_ACPI_IO_APIC_COUNT]; +#endif + +#if EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT > 0 // Type 0x02 + EFI_ACPI_3_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE Iso[EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT]; +#endif + +#if EFI_ACPI_NON_MASKABLE_INTERRUPT_SOURCE_COUNT > 0 // Type 0x03 + EFI_ACPI_3_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE NmiSource[EFI_ACPI_NON_MASKABLE_INTERRUPT_SOURCE_COUNT]; +#endif + +#if EFI_ACPI_LOCAL_APIC_NMI_COUNT > 0 // Type 0x04 + EFI_ACPI_3_0_LOCAL_APIC_NMI_STRUCTURE LocalApicNmi[EFI_ACPI_LOCAL_APIC_NMI_COUNT]; +#endif + +#if EFI_ACPI_LOCAL_APIC_ADDRESS_OVERRIDE_COUNT > 0 // Type 0x05 + EFI_ACPI_3_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE LocalApicOverride[EFI_ACPI_LOCAL_APIC_ADDRESS_OVERRIDE_COUNT]; +#endif + +#if EFI_ACPI_IO_SAPIC_COUNT > 0 // Type 0x06 + EFI_ACPI_3_0_IO_SAPIC_STRUCTURE IoSapic[EFI_ACPI_IO_SAPIC_COUNT]; +#endif + +#if EFI_ACPI_PROCESSOR_LOCAL_SAPIC_COUNT > 0 // Type 0x07 : This table changes in madt 2.0 + EFI_ACPI_3_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE LocalSapic[EFI_ACPI_PROCESSOR_LOCAL_SAPIC_COUNT]; +#endif + +#if EFI_ACPI_PLATFORM_INTERRUPT_SOURCES_COUNT > 0 // Type 0x08 + EFI_ACPI_3_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE PlatformInterruptSources[EFI_ACPI_PLATFORM_INTERRUPT_SOURCES_COUNT]; +#endif + +} EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE; + +#pragma pack() + +#endif diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Madt/Madt30.aslc b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Madt/Madt30.aslc new file mode 100644 index 0000000000..7b16120234 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Madt/Madt30.aslc @@ -0,0 +1,184 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Madt3.0.c + +Abstract: + + This file contains a structure definition for the ACPI 2.0 Multiple APIC + Description Table (MADT). Any changes to the MADT table require updating the + respective structure count in Madt.h and then adding the structure to the + MADT defined in this file. The table layout is defined in Madt.h and the + table contents are defined in Acpi3_0.h and Madt.h. + +--*/ + +// +// Statements that include other files +// +#include "Madt.h" +#include + +// +// Multiple APIC Description Table +// +EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE Madt = { + EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, // **Signatures are the same 1.0-3.0 because it says "APIC". + sizeof (EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE), // **Length + EFI_ACPI_5_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION, + // + // EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION, // **Table Revision must be 2.0 for ACPI 3.0 + // Checksum will be updated at runtime + // + 0x00, // **Check sum + // + // It is expected that these values will be programmed at runtime + // + ' ', // OEMID + ' ', // Creative way to + ' ', // make six bytes + ' ', // of space in + ' ', // a table for + ' ', // **OEMID + 0, // **OEM Table ID + EFI_ACPI_OEM_MADT_REVISION, // **OEM Revision + 0, // **Creator ID + 0, // **Creator Revision + // + // MADT specific fields + // + LOCAL_APIC_ADDRESS, // **Local APIC Address + EFI_ACPI_4_0_MULTIPLE_APIC_FLAGS, // **Flags + // + // Processor Local APIC Structure + // Correct processor order, Primary threads first then Hyper threads + // And correct APIC-ids + // This text below is included as a reference until Thurley is 100%: + // According to EDS the Local APIC ID is determined based of a bit structure + // Bit 24: Core ID Bit 25: Core Pair ID Bit 26-27: Reserved Bit 28-30: Socket ID Bit 31: Reserved + // 4 Sockets and 4 Cores per Socket. + // So possible LAPIC IDs 00, 01, 02, 03, 10, 11, 12, 13, 20, 21, 22, 23, 30, 31, 32, 33 + // Static Entries 00, 10, 20, 30, 01, 11, 21, 31, 02, 12, 22, 32, 03, 13, 23, 33 + // BSP needs to be first entry in table. Check before boot. If BSP non zero need to rotate the entries. + // Suppore BSP is LAPIC ID xy. Rotate the table by using formula [x + (y * 4)] + // So if BSP LAPIC ID is 21 then table rotated 6 times. + // End of Reference Text. + // Thurley is supposed to be 2 sockets, 4 cores, and hyperthreading available per each core. + // 2 (sockets) x 4 (cores) = 8 (processors non-HT), 8 (processors non-HT) x 2 (HT/proc) = 16 (HT procs) + // Rhyme & reason of the ordering below. This is a best guess ordering for now, + // Thurley EPS may give better info on LAPIC numbers. + // Ordering was established to help dissipate heat across two sockets evenly. + // Since logical processor number only has to be unique, I followed + // a similar approach to high end servers and have the first digit of the LAPIC + // id the socket number. + // + EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC, // Type 0x00 + sizeof (EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_STRUCTURE), // Length + 0x01, // Processor ID + 0x00, // Local APIC ID + 0x00000001, // Flags - Disabled (until initialized by platform driver) + EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC, // Type + sizeof (EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_STRUCTURE), // Length + 0x02, // Processor ID + 0x02, // Local APIC ID //Todo: Temp change APIC ID order for fixing VLV X0 not enable 2 CPU in Windows. + 0x00000001, // Flags - Disabled (until initialized by platform driver) + EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC, // Type + sizeof (EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_STRUCTURE), // Length + 0x03, // Processor ID + 0x04, // Local APIC ID + 0x00000001, // Flags - Disabled (until initialized by platform driver) + EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC, // Type + sizeof (EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_STRUCTURE), // Length + 0x04, // Processor ID + 0x06, // Local APIC ID + 0x00000001, // Flags - Disabled (until initialized by platform driver) + // + // *************** IO APIC Structure ****************** + // + // + // + // ************************** I/O APIC ************** + // + EFI_ACPI_3_0_IO_APIC, // Type 0x01 + sizeof (EFI_ACPI_3_0_IO_APIC_STRUCTURE), // Length + ICH_IOAPIC_ID, // IO APIC ID + EFI_ACPI_RESERVED_BYTE, // Reserved EFI_ACPI_RESERVED_BYTE + IO_APIC_ADDRESS, // IO APIC Address (physical) 0xFEC00000 + 0x18 * 0, // Global System Interrupt Base + + // + // Interrupt Source Override Structure: Sample + // + // EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE, // Type 0x02 + // sizeof (EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE),// Length + // 0x00, // Bus + // 0x00, // Source + // 0x00000000, // Global System Interrupt + // 0x0000, // Flags + // + // IRQ0=>IRQ2 Interrupt Source Override Structure + // + EFI_ACPI_3_0_INTERRUPT_SOURCE_OVERRIDE, // Type 0x02 + sizeof (EFI_ACPI_3_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE), // Length + 0x00, // Bus - ISA + 0x00, // Source - IRQ0 + 0x00000002, // Global System Interrupt - IRQ2 + 0x0000, // Flags - Conforms to specifications of the bus + // + // ISO (SCI Active High) Interrupt Source Override Structure + // + EFI_ACPI_3_0_INTERRUPT_SOURCE_OVERRIDE, // Type 0x02 + sizeof (EFI_ACPI_3_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE), // Length + 0x00, // Bus - ISA + 0x09, // Source - IRQ0 + 0x00000009, // Global System Interrupt - IRQ2 + 0x000D, // Flags - Level-tiggered, Active High + + + + EFI_ACPI_3_0_LOCAL_APIC_NMI, // Type + sizeof (EFI_ACPI_3_0_LOCAL_APIC_NMI_STRUCTURE), // Length + 0x01, // ACPI Processor ID + 0x000D, // Flags - Level-tiggered, Active High + 0x01, // Local APIC LINT# + EFI_ACPI_3_0_LOCAL_APIC_NMI, // Type + sizeof (EFI_ACPI_3_0_LOCAL_APIC_NMI_STRUCTURE), // Length + 0x02, // ACPI Processor ID + 0x000D, // Flags - Level-tiggered, Active High + 0x01, // Local APIC LINT# + EFI_ACPI_3_0_LOCAL_APIC_NMI, // Type + sizeof (EFI_ACPI_3_0_LOCAL_APIC_NMI_STRUCTURE), // Length + 0x03, // ACPI Processor ID + 0x000D, // Flags - Level-tiggered, Active High + 0x01, // Local APIC LINT# + EFI_ACPI_3_0_LOCAL_APIC_NMI, // Type + sizeof (EFI_ACPI_3_0_LOCAL_APIC_NMI_STRUCTURE), // Length + 0x04, // ACPI Processor ID + 0x000D, // Flags - Level-tiggered, Active High + 0x01, // Local APIC LINT# +}; + +VOID* +ReferenceAcpiTable ( + VOID + ) +{ + // + // Reference the table being generated to prevent the optimizer from + // removing the data structure from the executable + // + return (VOID*)&Madt; +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Mcfg/Mcfg.aslc b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Mcfg/Mcfg.aslc new file mode 100644 index 0000000000..0683ca459e --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Mcfg/Mcfg.aslc @@ -0,0 +1,92 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Mcfg.c + +Abstract: + + This file contains a structure definition for the ACPI Memory mapped + configuration space base address Description Table (MCFG). Any changes + to the MCFG table require updating the respective 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 McfgTable.h and Mcfg.h. + +--*/ + +// +// Statements that include other files +// +#include + +// +// MCFG Table definition +// +EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE MCFG = { + EFI_ACPI_3_0_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_SIGNATURE, + sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE), + EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_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, + // + // Beginning of MCFG specific fields + // + EFI_ACPI_RESERVED_QWORD, + // + // Sample Memory Mapped Configuration Space Base Address Structure + // + // 0x0, // Base Address + // 0x0, // PCI Segment Group Number + // 0x0, // Start Bus Number + // 0x0, // End Bus Number + // EFI_ACPI_RESERVED_DWORD, // Reserved + // + // Memory Mapped Configuration Space Base Address Structure + // + 0x0, // Base Address, will be updated by AcpiPlatform + 0x0, // PCI Segment Group Number + 0x0, // Start Bus Number + PLATFORM_MAX_BUS_NUM, // End Bus Number + EFI_ACPI_RESERVED_DWORD, // Reserved +}; + +VOID* +ReferenceAcpiTable ( + VOID + ) +{ + // + // Reference the table being generated to prevent the optimizer from + // removing the data structure from the executable + // + return (VOID*)&MCFG; +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PCI_DRC.ASL b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PCI_DRC.ASL new file mode 100644 index 0000000000..73b3d4db3d --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PCI_DRC.ASL @@ -0,0 +1,96 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + + + +Scope (\_SB.PCI0) +{ + + Device(PDRC) // PCI Device Resource Consumption + { + Name(_HID,EISAID("PNP0C02")) + + Name(_UID,1) + + Name(BUF0,ResourceTemplate() + { + // + // PCI Express BAR _BAS and _LEN will be updated in _CRS below according to B0:D0:F0:Reg.60h + // Forced hard code at the moment. + // + //Memory32Fixed(ReadWrite,0,0,PCIX) // PCIEX BAR + Memory32Fixed(ReadWrite,0x0E0000000,0x010000000,PCIX) + + // + // SPI BAR. Check if the hard code meets the real configuration. + // If not, dynamically update it like the _CRS method below. + // + Memory32Fixed(ReadWrite,0x0FED01000,0x01000,SPIB) // SPI BAR + + // + // PMC BAR. Check if the hard code meets the real configuration. + // If not, dynamically update it like the _CRS method below. + // + Memory32Fixed(ReadWrite,0x0FED03000,0x01000,PMCB) // PMC BAR + + // + // SMB BAR. Check if the hard code meets the real configuration. + // If not, dynamically update it like the _CRS method below. + // + Memory32Fixed(ReadWrite,0x0FED04000,0x01000,SMBB) // SMB BAR + + // + // IO BAR. Check if the hard code meets the real configuration. + // If not, dynamically update it like the _CRS method below. + // + Memory32Fixed(ReadWrite,0x0FED0C000,0x04000,IOBR) // IO BAR + + // + // ILB BAR. Check if the hard code meets the real configuration. + // If not, dynamically update it like the _CRS method below. + // + Memory32Fixed(ReadWrite,0x0FED08000,0x01000,ILBB) // ILB BAR + + // + // RCRB BAR _BAS will be updated in _CRS below according to B0:D31:F0:Reg.F0h + // + Memory32Fixed(ReadWrite,0x0FED1C000,0x01000,RCRB) // RCRB BAR + + // + // Local APIC range(0xFEE0_0000 to 0xFEEF_FFFF) + // + Memory32Fixed (ReadOnly, 0x0FEE00000, 0x0100000, LIOH) + + // + // MPHY BAR. Check if the hard code meets the real configuration. + // If not, dynamically update it like the _CRS method below. + // + Memory32Fixed(ReadWrite,0x0FEF00000,0x0100000,MPHB) // MPHY BAR + }) + + Method(_CRS,0,Serialized) + { + + Return(BUF0) + } + + } +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Pch.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Pch.asl new file mode 100644 index 0000000000..38dac87bcd --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Pch.asl @@ -0,0 +1,685 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + + +Scope(\) +{ + // + // Define VLV ABASE I/O as an ACPI operating region. The base address + // can be found in Device 31, Registers 40-43h. + // + OperationRegion(PMIO, SystemIo, \PMBS, 0x46) + Field(PMIO, ByteAcc, NoLock, Preserve) + { + , 8, + PWBS, 1, // Power Button Status + Offset(0x20), + , 13, + PMEB, 1, // PME_B0_STS + Offset(0x42), // General Purpose Control + , 1, + GPEC, 1 + } + Field(PMIO, ByteAcc, NoLock, WriteAsZeros) + { + Offset(0x20), // GPE0 Status + , 4, + PSCI, 1, // PUNIT SCI Status + SCIS, 1 // GUNIT SCI Status + } + + + + // + // Define a Memory Region that will allow access to the PMC + // Register Block. Note that in the Intel Reference Solution, the PMC + // will get fixed up dynamically during POST. + // + OperationRegion(PMCR, SystemMemory, \PFDR, 0x04)// PMC Function Disable Register + Field(PMCR,DWordAcc,Lock,Preserve) + { + Offset(0x00), // Function Disable Register + L10D, 1, // (0) LPIO1 DMA Disable + L11D, 1, // (1) LPIO1 PWM #1 Disable + L12D, 1, // (2) LPIO1 PWM #2 Disable + L13D, 1, // (3) LPIO1 HS-UART #1 Disable + L14D, 1, // (4) LPIO1 HS-UART #2 Disable + L15D, 1, // (5) LPIO1 SPI Disable + , 2, // (6:7) Reserved + SD1D, 1, // (8) SCC SDIO #1 Disable + SD2D, 1, // (9) SCC SDIO #2 Disable + SD3D, 1, // (10) SCC SDIO #3 Disable + HSID, 1, // (11) + HDAD, 1, // (12) Azalia Disable + LPED, 1, // (13) LPE Disable + OTGD, 1, // (14) USB OTG Disable + , 1, // (15) USH Disable + , 1, // (16) + , 1, // (17) + , 1, // (18) USB Disable + , 1, // (19) SEC Disable + RP1D, 1, // (20) Root Port 0 Disable + RP2D, 1, // (21) Root Port 1 Disable + RP3D, 1, // (22) Root Port 2 Disable + RP4D, 1, // (23) Root Port 3 Disable + L20D, 1, // (24) LPIO2 DMA Disable + L21D, 1, // (25) LPIO2 I2C #1 Disable + L22D, 1, // (26) LPIO2 I2C #2 Disable + L23D, 1, // (27) LPIO2 I2C #3 Disable + L24D, 1, // (28) LPIO2 I2C #4 Disable + L25D, 1, // (29) LPIO2 I2C #5 Disable + L26D, 1, // (30) LPIO2 I2C #6 Disable + L27D, 1 // (31) LPIO2 I2C #7 Disable + } + + + OperationRegion(CLKC, SystemMemory, \PCLK, 0x18)// PMC CLK CTL Registers + Field(CLKC,DWordAcc,Lock,Preserve) + { + Offset(0x00), // PLT_CLK_CTL_0 + CKC0, 2, + CKF0, 1, + , 29, + Offset(0x04), // PLT_CLK_CTL_1 + CKC1, 2, + CKF1, 1, + , 29, + Offset(0x08), // PLT_CLK_CTL_2 + CKC2, 2, + CKF2, 1, + , 29, + Offset(0x0C), // PLT_CLK_CTL_3 + CKC3, 2, + CKF3, 1, + , 29, + Offset(0x10), // PLT_CLK_CTL_4 + CKC4, 2, + CKF4, 1, + , 29, + Offset(0x14), // PLT_CLK_CTL_5 + CKC5, 2, + CKF5, 1, + , 29, + } +} //end Scope(\) + +scope (\_SB) +{ + Device(LPEA) + { + Name (_ADR, 0) + Name (_HID, "80860F28") + Name (_CID, "80860F28") + //Name (_CLS, Package (3) {0x04, 0x01, 0x00}) + Name (_DDN, "Intel(R) Low Power Audio Controller - 80860F28") + Name (_SUB, "80867270") + Name (_UID, 1) + Name (_DEP, Package() {\_SB.I2C2.RTEK}) + Name(_PR0,Package() {PLPE}) + + Method (_STA, 0x0, NotSerialized) + { + If (LAnd(LAnd(LEqual(LPEE, 2), LEqual(LPED, 0)), LEqual(OSEL, 0))) + { + Return (0xF) + } + Return (0x0) + } + + Method (_DIS, 0x0, NotSerialized) + { + //Add a dummy disable function + } + + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0xFE400000, 0x00200000, BAR0) // MMIO 1 - LPE MMIO + Memory32Fixed (ReadWrite, 0xFE830000, 0x00001000, BAR1) // MMIO 2 - Shadowed PCI Config Space + Memory32Fixed (ReadWrite, 0x55AA55AA, 0x00100000, BAR2) // LPE Memory Bar Allocate during post + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {24} + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {25} + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {26} + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {27} + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {28} + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {29} + GpioInt(Edge, ActiveBoth, ExclusiveAndWake, PullNone, 0,"\\_SB.GPO2") {28} // Audio jack interrupt + } + ) + + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + Store(LPE0, B0BA) + CreateDwordField(^RBUF, ^BAR1._BAS, B1BA) + Store(LPE1, B1BA) + CreateDwordField(^RBUF, ^BAR2._BAS, B2BA) + Store(LPE2, B2BA) + Return (RBUF) + } + + OperationRegion (KEYS, SystemMemory, LPE1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } + + PowerResource(PLPE, 0, 0) // Power Resource for LPEA + { + Method (_STA) + { + Return (1) // Power Resource is always available. + } + + Method (_ON) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + + Method (_OFF) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + } // End PLPE + } // End "Low Power Engine Audio" + + Device(LPA2) + { + Name (_ADR, 0) + Name (_HID, "LPE0F28") // _HID: Hardware ID + Name (_CID, "LPE0F28") // _CID: Compatible ID + Name (_DDN, "Intel(R) SST Audio - LPE0F28") // _DDN: DOS Device Name + Name (_SUB, "80867270") + Name (_UID, 1) + Name (_DEP, Package() {\_SB.I2C2.RTEK}) + Name(_PR0,Package() {PLPE}) + + Method (_STA, 0x0, NotSerialized) + { + If (LAnd(LAnd(LEqual(LPEE, 2), LEqual(LPED, 0)), LEqual(OSEL, 1))) + { + Return (0xF) + } + Return (0x0) + } + + Method (_DIS, 0x0, NotSerialized) + { + //Add a dummy disable function + } + + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x55AA55AA, 0x00100000, BAR2) // LPE Memory Bar Allocate during post + Memory32Fixed (ReadWrite, 0x55AA55AA, 0x00000100, SHIM) + Memory32Fixed (ReadWrite, 0x55AA55AA, 0x00001000, MBOX) + Memory32Fixed (ReadWrite, 0x55AA55AA, 0x00014000, IRAM) + Memory32Fixed (ReadWrite, 0x55AA55AA, 0x00028000, DRAM) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {29} + Memory32Fixed (ReadWrite, 0xFE830000, 0x00001000, BAR1) // MMIO 2 - Shadowed PCI Config Space + } + ) + + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^SHIM._BAS, SHBA) + Add(LPE0, 0x140000, SHBA) + CreateDwordField(^RBUF, ^MBOX._BAS, MBBA) + Add(LPE0, 0x144000, MBBA) + CreateDwordField(^RBUF, ^IRAM._BAS, IRBA) + Add(LPE0, 0xC0000, IRBA) + CreateDwordField(^RBUF, ^DRAM._BAS, DRBA) + Add(LPE0, 0x100000, DRBA) + CreateDwordField(^RBUF, ^BAR1._BAS, B1BA) + Store(LPE1, B1BA) + CreateDwordField(^RBUF, ^BAR2._BAS, B2BA) + Store(LPE2, B2BA) + Return (RBUF) + } + + OperationRegion (KEYS, SystemMemory, LPE1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } + + PowerResource(PLPE, 0, 0) // Power Resource for LPEA + { + Method (_STA) + { + Return (1) // Power Resource is always available. + } + + Method (_ON) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + + Method (_OFF) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + } // End PLPE + + Device (ADMA) + { + Name (_ADR, Zero) // _ADR: Address + Name (_HID, "DMA0F28") // _HID: Hardware ID + Name (_CID, "DMA0F28") // _CID: Compatible ID + Name (_DDN, "Intel(R) Audio DMA0 - DMA0F28") // _DDN: DOS Device Name + Name (_UID, One) // _UID: Unique ID + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x55AA55AA, 0x00001000, DMA0) // LPE BASE + LPE DMA0 offset + Memory32Fixed (ReadWrite, 0x55AA55AA, 0x00001000, SHIM) // LPE BASE + LPE SHIM offset + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {24} + }) + + Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings + { + CreateDwordField(^RBUF, ^DMA0._BAS, D0BA) + Add(LPE0, 0x98000, D0BA) + CreateDwordField(^RBUF, ^SHIM._BAS, SHBA) + Add(LPE0, 0x140000, SHBA) + Return (RBUF) + } + } + } // End "Low Power Engine Audio" for Android +} + +scope (\_SB.PCI0) +{ + + // + // Serial ATA Host Controller - Device 19, Function 0 + // + + Device(SATA) + { + Name(_ADR,0x00130000) + // + // SATA Methods pulled in via SSDT. + // + + OperationRegion(SATR, PCI_Config, 0x74,0x4) + Field(SATR,WordAcc,NoLock,Preserve) + { + Offset(0x00), // 0x74, PMCR + , 8, + PMEE, 1, //PME_EN + , 6, + PMES, 1 //PME_STS + } + + Method (_STA, 0x0, NotSerialized) + { + Return(0xf) + } + + Method(_DSW, 3) + { + } // End _DSW + } + + // + // For eMMC 4.41 PCI mode in order to present non-removable device under Windows environment + // + Device(EM41) + { + Name(_ADR,0x00100000) + OperationRegion(SDIO, PCI_Config, 0x84,0x4) + Field(SDIO,WordAcc,NoLock,Preserve) + { + Offset(0x00), // 0x84, PMCR + , 8, + PMEE, 1, //PME_EN + , 6, + PMES, 1 //PME_STS + } + + Method (_STA, 0x0, NotSerialized) + { + If (LAnd(LEqual(PCIM, 1), LEqual(SD1D, 0))) + { + Return(0xF) + } + Else + { + Return(0x0) + } + } + + Method(_DSW, 3) + { + } // End _DSW + + Device (CARD) + { + Name (_ADR, 0x00000008) + Method(_RMV, 0x0, NotSerialized) + { + Return (0) + } // End _DSW + } + } + + // + // For eMMC 4.5 PCI mode in order to present non-removable device under Windows environment + // + Device(EM45) + { + Name(_ADR,0x00170000) + OperationRegion(SDIO, PCI_Config, 0x84,0x4) + Field(SDIO,WordAcc,NoLock,Preserve) + { + Offset(0x00), // 0x84, PMCR + , 8, + PMEE, 1, //PME_EN + , 6, + PMES, 1 //PME_STS + } + + Method (_STA, 0x0, NotSerialized) + { + If (LAnd(LEqual(PCIM, 1), LEqual(HSID, 0))) + { + Return(0xF) + } + Else + { + Return(0x0) + } + } + + Method(_DSW, 3) + { + } // End _DSW + + Device (CARD) + { + Name (_ADR, 0x00000008) + Method(_RMV, 0x0, NotSerialized) + { + Return (0) + } // End _DSW + } + } + // + // For SD Host Controller (Bus 0x00 : Dev 0x12 : Func 0x00) PCI mode in order to present non-removable device under Windows environment + // + Device(SD12) + { + Name(_ADR,0x00120000) + + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 0)) { + Return (0x0) + } + + // + // If device is disabled. + // + If (LEqual(SD3D, 1)) + { + Return (0x0) + } + + Return (0xF) + } + + Device (CARD) + { + Name (_ADR, 0x00000008) + Method(_RMV, 0x0, NotSerialized) + { + // SDRM = 0 non-removable; + If (LEqual(SDRM, 0)) + { + Return (0) + } + + Return (1) + } + } + } + + // xHCI Controller - Device 20, Function 0 + include("PchXhci.asl") + + // + // High Definition Audio Controller - Device 27, Function 0 + // + Device(HDEF) + { + Name(_ADR, 0x001B0000) + include("PchAudio.asl") + + Method (_STA, 0x0, NotSerialized) + { + If (LEqual(HDAD, 0)) + { + Return(0xf) + } + Return(0x0) + } + + Method(_DSW, 3) + { + } // End _DSW + } // end "High Definition Audio Controller" + + + + // + // PCIE Root Port #1 + // + Device(RP01) + { + Name(_ADR, 0x001C0000) + include("PchPcie.asl") + Name(_PRW, Package() {9, 4}) + + Method(_PRT,0) + { + If(PICM) { Return(AR04) }// APIC mode + Return (PR04) // PIC Mode + } // end _PRT + } // end "PCIE Root Port #1" + + // + // PCIE Root Port #2 + // + Device(RP02) + { + Name(_ADR, 0x001C0001) + include("PchPcie.asl") + Name(_PRW, Package() {9, 4}) + + Method(_PRT,0) + { + If(PICM) { Return(AR05) }// APIC mode + Return (PR05) // PIC Mode + } // end _PRT + + } // end "PCIE Root Port #2" + + // + // PCIE Root Port #3 + // + Device(RP03) + { + Name(_ADR, 0x001C0002) + include("PchPcie.asl") + Name(_PRW, Package() {9, 4}) + Method(_PRT,0) + { + If(PICM) { Return(AR06) }// APIC mode + Return (PR06) // PIC Mode + } // end _PRT + + } // end "PCIE Root Port #3" + + // + // PCIE Root Port #4 + // + Device(RP04) + { + Name(_ADR, 0x001C0003) + include("PchPcie.asl") + Name(_PRW, Package() {9, 4}) + Method(_PRT,0) + { + If(PICM) { Return(AR07) }// APIC mode + Return (PR07) // PIC Mode + } // end _PRT + + } // end "PCIE Root Port #4" + + + Scope(\_SB) + { + // + // Dummy power resource for USB D3 cold support + // + PowerResource(USBC, 0, 0) + { + Method(_STA) { Return (0xF) } + Method(_ON) {} + Method(_OFF) {} + } + } + // + // EHCI Controller - Device 29, Function 0 + // + Device(EHC1) + { + Name(_ADR, 0x001D0000) + Name(_DEP, Package(0x1) + { + PEPD + }) + include("PchEhci.asl") + Name(_PRW, Package() {0x0D, 4}) + + OperationRegion(USBR, PCI_Config, 0x54,0x4) + Field(USBR,WordAcc,NoLock,Preserve) + { + Offset(0x00), // 0x54, PMCR + , 8, + PMEE, 1, //PME_EN + , 6, + PMES, 1 //PME_STS + } + + Method (_STA, 0x0, NotSerialized) + { + If(LEqual(XHCI, 0)) //XHCI is not present. It means EHCI is there + { + Return (0xF) + } Else + { + Return (0x0) + } + } + + Method (_RMV, 0, NotSerialized) + { + Return (0x0) + } + // + // Create a dummy PR3 method to indicate to the PCI driver + // that the device is capable of D3 cold + // + Method(_PR3, 0x0, NotSerialized) + { + return (Package() {\_SB.USBC}) + } + + } // end "EHCI Controller" + + // + // SMBus Controller - Device 31, Function 3 + // + Device(SBUS) + { + Name(_ADR,0x001F0003) + Include("PchSmb.asl") + } + + Device(SEC0) + { + Name (_ADR, 0x001a0000) // Device 0x1a, Function 0 + Name(_DEP, Package(0x1) + { + PEPD + }) + + + OperationRegion (PMEB, PCI_Config, 0x84, 0x04) //PMECTRLSTATUS + Field (PMEB, WordAcc, NoLock, Preserve) + { + , 8, + PMEE, 1, //bit8 PMEENABLE + , 6, + PMES, 1 //bit15 PMESTATUS + } + + // Arg0 -- integer that contains the device wake capability control (0-disable 1- enable) + // Arg1 -- integer that contains target system state (0-4) + // Arg2 -- integer that contains the target device state + Method (_DSW, 3, NotSerialized) // _DSW: Device Sleep Wake + { + } + + Method (_CRS, 0, NotSerialized) + { + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x1e000000, 0x2000000) + }) + + If (LEqual(PAVP, 2)) + { + Return (RBUF) + } + Return (ResourceTemplate() {}) + } + + Method (_STA) + { + If (LNotEqual(PAVP, 0)) + { + Return (0xF) + } + Return (0x0) + } + } // Device(SEC0) + +} // End scope (\_SB.PCI0) diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchAudio.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchAudio.asl new file mode 100644 index 0000000000..7c93c3af41 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchAudio.asl @@ -0,0 +1,42 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ +// +// High Definition Audio - Device 27, Function 0 +// +OperationRegion(HDAR, PCI_Config, 0x4C,0x10) +Field(HDAR,WordAcc,NoLock,Preserve) +{ + Offset(0x00), // 0x4C, Dock Control Register + DCKA, 1, // Dock Attach + , 7, + Offset(0x01), // 04Dh, Dock Status Register + DCKM, 1, // Dock Mated + , 6, + DCKS, 1, // Docking Supported + Offset(0x08), // 0x54, Power Management Control and Status Register + , 8, + PMEE, 1, // PME_EN + , 6, + PMES, 1 // PME Status +} + + + diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchEhci.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchEhci.asl new file mode 100644 index 0000000000..84626e353b --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchEhci.asl @@ -0,0 +1,275 @@ +/***************************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved *; +;* *; +;* This program and the accompanying materials are licensed and made available under *; +;* the terms and conditions of the BSD License that accompanies this distribution. *; +;* The full text of the license may be found at *; +;* http://opensource.org/licenses/bsd-license.php. *; +;* *; +;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, *; +;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. *; +;* *; +;* *; +;* *; +;***************************************************************************************/ + +OperationRegion(PWKE,PCI_Config,0x62,0x04) + +Field(PWKE,DWordAcc,NoLock,Preserve) +{ + , 1, + PWUC, 8 // Port Wake Up Capability Mask +} + +Method(_PSW,1) +{ + If(Arg0) + { + Store(Ones,PWUC) + } + Else + { + Store(0,PWUC) + } +} + +// Leaves the USB ports on in S3/S4 to allow +// the ability to Wake from USB. Therefore, define +// the below control methods to state D2 entry during +// the given S-State. + +Method(_S3D,0) +{ + Return(2) +} + +Method(_S4D,0) +{ + Return(2) +} + +Device(HUBN) +{ + Name(_ADR, Zero) + Device(PR01) + { + Name(_ADR, One) + + // + // There will have "Generic USB Hub" existed at Port 1 of each EHCI controller + // in Windows "Device Manager" while RMH is enabled, so need to add _UPC + // and _PLD to report OS that it's not user visible to pass WHQL: Single Computer + // Display Object test in Win7 + // + Name(_UPC, Package() + { + 0xFF, // Port is connectable + 0x00, // Connector type - Type "A" + 0x00000000, // Reserved 0 - must be zero + 0x00000000 + }) // Reserved 1 - must be zero + + Name(_PLD, Package() + { + Buffer (0x10) + { + 0x81, 0x00, 0x00, 0x00, // Revision 1, Ignore color + 0x00, 0x00, 0x00, 0x00, + 0x30, 0x1C, 0x00, 0x00, // Panel Unknown, Shape Unknown + 0x00, 0x00, 0x00, 0x00 + } + }) + + Device(PR11) + { + Name(_ADR, One) + Name(_UPC, Package() + { + 0xFF, // Port is connectable + 0xFF, // Proprietary connector + 0x00000000, // Reserved 0 - must be zero + 0x00000000 + }) // Reserved 1 - must be zero + Name(_PLD, Package() + { + Buffer (0x10) + { + 0x81, 0x00, 0x00, 0x00, // Revision 1, Ignore color + 0x00, 0x00, 0x00, 0x00, + 0xE1, 0x1C, 0x00, 0x00, // Front Panel, Vertical Upper, Horz. Left, Shape Unknown + 0x00, 0x00, 0x00, 0x00 + } + }) + } + + Device(PR12) + { + Name(_ADR, 0x02) + Name(_UPC, Package() + { + 0xFF, // Port is connectable + 0xFF, // Proprietary connector + 0x00000000, // Reserved 0 - must be zero + 0x00000000 + }) // Reserved 1 - must be zero + Name(_PLD, Package() + { + Buffer (0x10) + { + 0x81, 0x00, 0x00, 0x00, // Revision 1, Ignore color + 0x00, 0x00, 0x00, 0x00, + 0xE1, 0x1D, 0x00, 0x00, // Front Panel, Vertical Center, Horz. Left, Shape Unknown + 0x00, 0x00, 0x00, 0x00 + } + }) + } + + Device(PR13) + { + Name(_ADR, 0x03) + Name(_UPC, Package() + { + 0xFF, // Port is connectable + 0xFF, // Proprietary connector + 0x00000000, // Reserved 0 - must be zero + 0x00000000 + }) // Reserved 1 - must be zero + Name(_PLD, Package() + { + Buffer (0x10) + { + 0x81, 0x00, 0x00, 0x00, // Revision 1, Ignore color + 0x00, 0x00, 0x00, 0x00, + 0xE1, 0x1D, 0x00, 0x00, // Front Panel, Vertical Center, Horz. Left, Shape Unknown + 0x00, 0x00, 0x00, 0x00 + } + }) + } + + Device(PR14) + { + Name(_ADR, 0x04) + Name(_UPC, Package() + { + 0xFF, // Port is connectable + 0xFF, // Proprietary connector + 0x00000000, // Reserved 0 - must be zero + 0x00000000 + }) // Reserved 1 - must be zero + + Name(_PLD, Package() + { + Buffer (0x10) + { + 0x81, 0x00, 0x00, 0x00, // Revision 1, Ignore color + 0x00, 0x00, 0x00, 0x00, + 0xE1, 0x1E, 0x00, 0x00, // Front Panel, Vertical Lower, Horz. Left, Shape Unknown + 0x00, 0x00, 0x00, 0x00 + } + }) + + // copy USB Sideband Deferring GPE Vector (HOST_ALERT#1) to DSM method + Include("UsbSbd.asl") + } + + Device(PR15) + { + Name(_ADR, 0x05) + Name(_UPC, Package() + { + 0xFF, // Port is connectable + 0xFF, // Proprietary connector + 0x00000000, // Reserved 0 - must be zero + 0x00000000 + }) // Reserved 1 - must be zero + Name(_PLD, Package() + { + Buffer (0x10) + { + 0x81, 0x00, 0x00, 0x00, // Revision 1, Ignore color + 0x00, 0x00, 0x00, 0x00, + 0xB1, 0x1E, 0x00, 0x00, // Panel Unknown, Shape Unknown + 0x00, 0x00, 0x00, 0x00 + } + }) + // copy USB Sideband Deferring GPE Vector (HOST_ALERT#2) to DSM method + Include("UsbSbd.asl") + } + + Device(PR16) + { + Name(_ADR, 0x06) + Name(_UPC, Package() + { + 0xFF, // Port is connectable + 0xFF, // Proprietary connector + 0x00000000, // Reserved 0 - must be zero + 0x00000000 + }) // Reserved 1 - must be zero + Name(_PLD, Package() + { + Buffer (0x10) + { + 0x81, 0x00, 0x00, 0x00, // Revision 1, Ignore color + 0x00, 0x00, 0x00, 0x00, + 0xB1, 0x1E, 0x00, 0x00, // Panel Unknown, Shape Unknown + 0x00, 0x00, 0x00, 0x00 + } + }) + // copy USB Sideband Deferring GPE Vector (HOST_ALERT#1) to DSM method + Include("UsbSbd.asl") + } + + Device(PR17) + { + Name(_ADR, 0x07) + Name(_UPC, Package() + { + 0xFF, // Port is connectable + 0xFF, // Proprietary connector + 0x00000000, // Reserved 0 - must be zero + 0x00000000 + }) // Reserved 1 - must be zero + Name(_PLD, Package() + { + Buffer (0x10) + { + 0x81, 0x00, 0x00, 0x00, // Revision 1, Ignore color + 0x00, 0x00, 0x00, 0x00, + 0xB1, 0x1E, 0x00, 0x00, // Panel Unknown, Shape Unknown + 0x00, 0x00, 0x00, 0x00 + } + }) + // copy USB Sideband Deferring GPE Vector (HOST_ALERT#2) to DSM method + Include("UsbSbd.asl") + } + + Device(PR18) + { + Name(_ADR, 0x08) + Name(_UPC, Package() + { + 0xFF, // Port is connectable + 0xFF, // Proprietary connector + 0x00000000, // Reserved 0 - must be zero + 0x00000000 + }) // Reserved 1 - must be zero + Name(_PLD, Package() + { + Buffer (0x10) + { + 0x81, 0x00, 0x00, 0x00, // Revision 1, Ignore color + 0x00, 0x00, 0x00, 0x00, + 0xB1, 0x1E, 0x00, 0x00, // Panel Unknown, Shape Unknown + 0x00, 0x00, 0x00, 0x00 + } + }) + } + } // End of PR01 +} // End of HUBN diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchLpss.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchLpss.asl new file mode 100644 index 0000000000..3e61e7925b --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchLpss.asl @@ -0,0 +1,1096 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ +// +// LPIO1 DMA#1 (Synopsis GP DMA) +// +Device (GDM1) +{ + Name (_HID, "INTL9C60") + Name (_DDN, "Intel(R) DMA Controller #1 - INTL9C60") + Name (_UID, 1) + + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00004000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {42} // DMA #1 IRQ + }) + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(D10A, B0BA) + Store(D10L, B0LN) + Return (RBUF) + } + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(D10A, 0), LEqual(L10D, 1))) + { + Return (0x0) + } + Return (0xF) + } +} + +// +// LPIO1 DMA#2 (Synopsis GP DMA) +// +Device (GDM2) +{ + Name (_HID, "INTL9C60") + Name (_DDN, "Intel(R) DMA Controller #2 - INTL9C60") + Name (_UID, 2) + + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00004000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {43} // DMA #2 IRQ + }) + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(D20A, B0BA) + Store(D20L, B0LN) + Return (RBUF) + } + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(D20A, 0), LEqual(L20D, 1))) + { + Return (0x0) + } + Return (0xF) + } +} + +// +// LPIO1 PWM #1 +// +Device(PWM1) +{ + Name (_ADR, 0) + Name (_HID, "80860F09") + Name (_CID, "80860F09") + Name (_DDN, "Intel(R) PWM Controller #1 - 80860F08") + Name (_UID, 1) + + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + }) + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(P10A, B0BA) + Store(P10L, B0LN) + Return (RBUF) + } + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(P10A, 0), LEqual(L11D, 1))) + { + Return (0x0) + } + Return (0xF) + } +} + +// +// LPIO1 PWM #2 +// +Device(PWM2) +{ + Name (_ADR, 0) + Name (_HID, "80860F09") + Name (_CID, "80860F09") + Name (_DDN, "Intel(R) PWM Controller #2 - 80860F09") + Name (_UID, 2) + + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + }) + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(P20A, B0BA) + Store(P20L, B0LN) + Return (RBUF) + } + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(P20A, 0), LEqual(L12D, 1))) + { + Return (0x0) + } + Return (0xF) + } +} + +// +// LPIO1 HS-UART #1 +// +Device(URT1) +{ + Name (_ADR, 0) + Name (_HID, "80860F0A") + Name (_CID, "80860F0A") + Name (_DDN, "Intel(R) HS-UART Controller #1 - 80860F0A") + Name (_UID, 1) + Name(_DEP, Package(0x1) + { + PEPD + }) + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {39} // HS-UART #1 IRQ + + FixedDMA(0x2, 0x2, Width32Bit, ) + FixedDMA(0x3, 0x3, Width32Bit, ) + }) + Method (_HRV, 0x0, NotSerialized) + { + Return (SOCS) + } + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(U10A, B0BA) + Store(U10L, B0LN) + Return (RBUF) + } + + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(U10A, 0), LEqual(L13D, 1))) + { + Return (0x0) + } + Return (0xF) + } + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + + OperationRegion (KEYS, SystemMemory, U11A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } +}// Device (URT1) + +// +// LPIO1 HS-UART #2 +// +Device(URT2) +{ + Name (_ADR, 0) + Name (_HID, "80860F0A") + Name (_CID, "80860F0A") + Name (_DDN, "Intel(R) HS-UART Controller #2 - 80860F0C") + Name (_UID, 2) + + Name(_DEP, Package(0x1) + { + PEPD + }) + + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {40} // HS-UART #2 IRQ + + FixedDMA(0x4, 0x4, Width32Bit, ) + FixedDMA(0x5, 0x5, Width32Bit, ) + }) + + Method (_HRV, 0x0, NotSerialized) + { + Return (SOCS) + } + + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(U20A, B0BA) + Store(U20L, B0LN) + Return (RBUF) + } + + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(U20A, 0), LEqual(L14D, 1))) + { + Return (0x0) + } + Return (0xF) + } + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + + OperationRegion (KEYS, SystemMemory, U21A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } +}// Device (URT2) + +// +// LPIO1 SPI +// +Device(SPI1) +{ + Name (_ADR, 0) + Name (_HID, "80860F0E") + Name (_CID, "80860F0E") + Name (_UID, "0") // Static bus number assignment + Name(_DEP, Package(0x1) + { + PEPD + }) + Name (_DDN, "Intel(R) SPI Controller - 80860F0E") + + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {41} // SPI IRQ + + FixedDMA(0x0, 0x0, Width32Bit, ) + FixedDMA(0x1, 0x1, Width32Bit, ) + }) + + Method (_HRV, 0x0, NotSerialized) + { + Return (SOCS) + } + + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(SP0A, B0BA) + Store(SP0L, B0LN) + Return (RBUF) + } + + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(SP0A, 0), LEqual(L15D, 1))) + { + Return (0x0) + } + Return (0xF) + } + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + + OperationRegion (KEYS, SystemMemory, SP1A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } +}// Device (SPI1) + +// +// LPIO2 I2C #1 +// +Device(I2C1) +{ + Name (_ADR, 0) + Name (_HID, "80860F41") + Name (_CID, "80860F41") + Name(_DEP, Package(0x1) + { + PEPD + }) + Name (_DDN, "Intel(R) I2C Controller #1 - 80860F41") + Name (_UID, 1) + + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {32} // I2C #1 IRQ + + FixedDMA(0x10, 0x0, Width32Bit, ) + FixedDMA(0x11, 0x1, Width32Bit, ) + }) + + Method (SSCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x200, 0x200, 0x06 }) + Return (PKG) + } + Method (FMCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x55, 0x99, 0x06 }) + Return (PKG) + } + Method (FPCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x1b, 0x3a, 0x06 }) + Return (PKG) + } + + Method (_HRV, 0x0, NotSerialized) + { + Return (SOCS) + } + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(I10A, B0BA) + Store(I10L, B0LN) + Return (RBUF) + } + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(I10A, 0), LEqual(L21D, 1))) + { + Return (0x0) + } + Return (0xF) + + } + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + OperationRegion (KEYS, SystemMemory, I11A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } + +} + +// +// LPIO2 I2C #2 +// +Device(I2C2) +{ + Name (_ADR, 0) + Name (_HID, "80860F41") + Name (_CID, "80860F41") + Name(_DEP, Package(0x1) + { + PEPD + }) + Name (_DDN, "Intel(R) I2C Controller #2 - 80860F42") + Name (_UID, 2) + + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {33} // I2C #2 IRQ + + FixedDMA(0x12, 0x2, Width32Bit, ) + FixedDMA(0x13, 0x3, Width32Bit, ) + }) + + Method (SSCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x200, 0x200, 0x06 }) + Return (PKG) + } + Method (FMCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x55, 0x99, 0x06 }) + Return (PKG) + } + Method (FPCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x1b, 0x3a, 0x06 }) + Return (PKG) + } + + Method (_HRV, 0x0, NotSerialized) + { + Return (SOCS) + } + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(I20A, B0BA) + Store(I20L, B0LN) + Return (RBUF) + } + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(I20A, 0), LEqual(L22D, 1))) + { + Return (0x0) + } + Return (0xF) + } + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + + } + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + OperationRegion (KEYS, SystemMemory, I21A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } + + + // + // Realtek Audio Codec + // + Device (RTEK) //Audio Codec driver I2C + { + Name (_ADR, 0) + Name (_HID, "10EC5640") + Name (_CID, "10EC5640") + Name (_DDN, "RTEK Codec Controller " ) + Name (_UID, 1) + + + Method(_CRS, 0x0, Serialized) + { + Name(SBUF,ResourceTemplate () + { + I2CSerialBus(0x1C, //SlaveAddress: bus address + , //SlaveMode: default to ControllerInitiated + 400000, //ConnectionSpeed: in Hz + , //Addressing Mode: default to 7 bit + "\\_SB.I2C2", //ResourceSource: I2C bus controller name + , //ResourceSourceIndex: defaults to 0 + , //ResourceUsage: Defaults to ResourceConsumer + , //Descriptor Name: creates name for offset of resource descriptor + ) //VendorData + GpioInt(Edge, ActiveHigh, ExclusiveAndWake, PullNone, 0,"\\_SB.GPO2") {4} // AUD_INT + }) + Return (SBUF) + } + + Method (_STA, 0x0, NotSerialized) + { + + If (LEqual(LPEE, 2)) { // LPE enable/disable + Return(0xF) + } + Return(0) + } + + Method (_DIS, 0x0, NotSerialized) + { + + } + } // Device (RTEK) +} // Device (I2C2) + +// +// LPIO2 I2C #3 +// +Device(I2C3) +{ + Name (_ADR, 0) + Name (_HID, "80860F41") + Name (_CID, "80860F41") + Name (_DDN, "Intel(R) I2C Controller #3 - 80860F43") + Name (_UID, 3) + Name(_DEP, Package(0x1) + { + PEPD + }) + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {34} // I2C #3 IRQ + + FixedDMA(0x14, 0x4, Width32Bit, ) + FixedDMA(0x15, 0x5, Width32Bit, ) + }) + + Method (SSCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x200, 0x200, 0x06 }) + Return (PKG) + } + Method (FMCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x55, 0x99, 0x06 }) + Return (PKG) + } + Method (FPCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x1b, 0x3a, 0x06 }) + Return (PKG) + } + + Method (_HRV, 0x0, NotSerialized) + { + Return (SOCS) + } + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(I30A, B0BA) + Store(I30L, B0LN) + Return (RBUF) + } + + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(I30A, 0), LEqual(L23D, 1))) + { + Return (0x0) + } + Return (0xF) + } + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + + } + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + OperationRegion (KEYS, SystemMemory, I31A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } + + +} + +// +// LPIO2 I2C #4 +// +Device(I2C4) +{ + Name (_ADR, 0) + Name (_HID, "80860F41") + Name (_CID, "80860F41") + Name (_DDN, "Intel(R) I2C Controller #4 - 80860F44") + Name (_UID, 4) + Name(_DEP, Package(0x1) + { + PEPD + }) + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {35} // I2C #4 IRQ + + FixedDMA(0x16, 0x6, Width32Bit, ) + FixedDMA(0x17, 0x7, Width32Bit, ) + }) + + Method (SSCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x200, 0x200, 0x06 }) + Return (PKG) + } + Method (FMCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x55, 0x99, 0x06 }) + Return (PKG) + } + Method (FPCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x1b, 0x3a, 0x06 }) + Return (PKG) + } + + + Method (_HRV, 0x0, NotSerialized) + { + Return (SOCS) + } + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(I40A, B0BA) + Store(I40L, B0LN) + Return (RBUF) + } + + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(I40A, 0), LEqual(L24D, 1))) + { + Return (0x0) + } + Return (0xF) + } + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + + } + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + OperationRegion (KEYS, SystemMemory, I41A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } + + PowerResource (CLK0, 0x00, 0x0000) + { + Method (_STA, 0, NotSerialized) // _STA: Status + { + Return (CKC0) + } + + Method (_ON, 0, NotSerialized) // _ON_: Power On + { + Store (One, CKC0) + Store (One, CKF0) + Sleep (0x20) + } + + Method (_OFF, 0, NotSerialized) // _OFF: Power Off + { + Store (0x02, CKC0) + } + } + PowerResource (CLK1, 0x00, 0x0000) + { + Method (_STA, 0, NotSerialized) // _STA: Status + { + Return (CKC1) + } + + Method (_ON, 0, NotSerialized) // _ON_: Power On + { + Store (One, CKC1) + Store (One, CKF1) + Sleep (0x20) + } + + Method (_OFF, 0, NotSerialized) // _OFF: Power Off + { + Store (0x02, CKC1) + } + } +} + +// +// LPIO2 I2C #5 +// +Device(I2C5) +{ + Name (_ADR, 0) + Name (_HID, "80860F41") + Name (_CID, "80860F41") + Name (_DDN, "Intel(R) I2C Controller #5 - 80860F45") + Name (_UID, 5) + Name(_DEP, Package(0x1) + { + PEPD + }) + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {36} // I2C #5 IRQ + + FixedDMA(0x18, 0x0, Width32Bit, ) + FixedDMA(0x19, 0x1, Width32Bit, ) + }) + + Method (SSCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x200, 0x200, 0x06 }) + Return (PKG) + } + Method (FMCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x55, 0x99, 0x06 }) + Return (PKG) + } + Method (FPCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x1b, 0x3a, 0x06 }) + Return (PKG) + } + + Method (_HRV, 0x0, NotSerialized) + { + Return (SOCS) + } + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(I50A, B0BA) + Store(I50L, B0LN) + Return (RBUF) + } + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(I50A, 0), LEqual(L25D, 1))) + { + Return (0x0) + } + Return (0xF) + } + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + OperationRegion (KEYS, SystemMemory, I51A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } +} + +// +// LPIO2 I2C #6 +// +Device(I2C6) +{ + Name (_ADR, 0) + Name (_HID, "80860F41") + Name (_CID, "80860F41") + Name (_DDN, "Intel(R) I2C Controller #6 - 80860F46") + Name (_UID, 6) + Name(_DEP, Package(0x1) + { + PEPD + }) + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {37} // I2C #6 IRQ + + FixedDMA(0x1A, 0x02, Width32Bit, ) + FixedDMA(0x1B, 0x03, Width32Bit, ) + }) + + Method (SSCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x200, 0x200, 0x06 }) + Return (PKG) + } + Method (FMCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x55, 0x99, 0x06 }) + Return (PKG) + } + Method (FPCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x1b, 0x3a, 0x06 }) + Return (PKG) + } + + Method (_HRV, 0x0, NotSerialized) + { + Return (SOCS) + } + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(I60A, B0BA) + Store(I60L, B0LN) + Return (RBUF) + } + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(I60A, 0), LEqual(L26D, 1))) + { + Return (0x0) + } + Return (0xF) + } + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + OperationRegion (KEYS, SystemMemory, I61A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } +} + +// +// LPIO2 I2C #7 +// +Device(I2C7) +{ + Name (_ADR, 0) + Name (_HID, "80860F41") + Name (_CID, "80860F41") + //Name (_CLS, Package (3) {0x0C, 0x80, 0x00}) + Name (_DDN, "Intel(R) I2C Controller #7 - 80860F47") + Name (_UID, 7) + Name(_DEP, Package(0x1) + { + PEPD + }) + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {38} // I2C #7 IRQ + + FixedDMA(0x1C, 0x4, Width32Bit, ) + FixedDMA(0x1D, 0x5, Width32Bit, ) + }) + + Method (SSCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x200, 0x200, 0x06 }) + Return (PKG) + } + Method (FMCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x55, 0x99, 0x06 }) + Return (PKG) + } + Method (FPCN, 0x0, NotSerialized) + { + Name (PKG, Package(3) { 0x1b, 0x3a, 0x06 }) + Return (PKG) + } + + Method (_HRV, 0x0, NotSerialized) + { + Return (SOCS) + } + + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(I70A, B0BA) + Store(I70L, B0LN) + Return (RBUF) + } + + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(I70A, 0), LEqual(L27D, 1))) + { + Return (0x0) + } + Return (0xF) + } + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + + OperationRegion (KEYS, SystemMemory, I71A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } + +} + diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchPcie.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchPcie.asl new file mode 100644 index 0000000000..bfd73e4f13 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchPcie.asl @@ -0,0 +1,56 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + + +OperationRegion(PXCS,PCI_Config,0x40,0xC0) +Field(PXCS,AnyAcc, NoLock, Preserve) +{ + Offset(0x10), // LCTL - Link Control Register + L0SE, 1, // 0, L0s Entry Enabled + , 7, + Offset(0x12), // LSTS - Link Status Register + , 13, + LASX, 1, // 0, Link Active Status + Offset(0x1A), // SLSTS[7:0] - Slot Status Register + ABPX, 1, // 0, Attention Button Pressed + , 2, + PDCX, 1, // 3, Presence Detect Changed + , 2, + PDSX, 1, // 6, Presence Detect State + , 1, + Offset(0x20), // RSTS - Root Status Register + , 16, + PSPX, 1, // 16, PME Status +} + + +Device(PXSX) +{ + Name(_ADR, 0x00000000) + + // NOTE: Any PCIE Hot-Plug dependency for this port is + // specific to the CRB. Please modify the code based on + // your platform requirements. + + Name(_PRW, Package() {9,4}) +} + + diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchScc.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchScc.asl new file mode 100644 index 0000000000..60ff48d013 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchScc.asl @@ -0,0 +1,616 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ +Device (PEPD) +{ + Name (_HID, "INT3396") + Name(_CID, 0x800dd041) + Name (_UID, 0x1) + + // Indicates if the platform PEP has loaded + Name(PEPP, Zero) + + // Devices score-boarded by the PEP, Rev0 format + Name (DEVS, Package() {0}) + + // Devices score-boarded by the PEP, Rev1 format + Name(DEVX, Package() + { + Package () {"\\_SB.PCI0.XHC1", 0x1}, + Package () {"\\_SB.PCI0.EHC1", 0x1}, + Package () {"\\_SB.PCI0.GFX0", 0x1}, + Package () {"\\_SB.PCI0.GFX0.ISP0", 0x1}, + Package () {"\\_SB.PCI0.SEC0", 0x1}, + Package () {"\\_SB.I2C1", 0x1}, + Package () {"\\_SB.I2C2", 0x1}, + Package () {"\\_SB.I2C3", 0x1}, + Package () {"\\_SB.I2C4", 0x1}, + Package () {"\\_SB.I2C5", 0x1}, + Package () {"\\_SB.I2C6", 0x1}, + Package () {"\\_SB.I2C7", 0x1}, + Package () {"\\_SB.SDHA", 0x1}, + Package () {"\\_SB.SDHB", 0x1}, + Package () {"\\_SB.SDHC", 0x1}, + Package () {"\\_SB.SPI1", 0x1}, + Package () {"\\_SB.URT1", 0x1}, + Package () {"\\_SB.URT2", 0x1}, + }) + // Crashdump device package + Name(CDMP, Package(2) {}) + // Device dependency for uPEP + Name(DEVY, Package() + { + Package() {"\\_PR.CPU0", 0x1, Package() {Package() {0xFF, 0}}}, + Package() {"\\_PR.CPU1", 0x1, Package() {Package() {0xFF, 0}}}, + Package() {"\\_PR.CPU2", 0x1, Package() {Package() {0xFF, 0}}}, + Package() {"\\_PR.CPU3", 0x1, Package() {Package() {0xFF, 0}}}, + Package() {"\\_SB.I2C1", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.I2C2", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.I2C3", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.I2C4", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.I2C5", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.I2C6", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.I2C7", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.PCI0.GFX0", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.PCI0.SEC0", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.PCI0.XHC1", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.PCI0.GFX0.ISP0", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.LPEA", 0x1, Package() {Package() {0x0,3}, Package() {0x1,0}, Package() {0x2,3}, Package() {0x3,3}}}, + Package() {"\\_SB.SDHA", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.SDHB", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.SDHC", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.SPI1", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.URT1", 0x1, Package() {Package() {0xFF,3}}}, + Package() {"\\_SB.URT2", 0x1, Package() {Package() {0xFF,3}}} + }) + // BCCD crashdump information + Name(BCCD, Package() + { + Package() + { + "\\_SB.SDHA", + Package() + { + Package() { Package() {0, 32, 0, 3, 0xFFFFFFFFFFFFFFFF}, Package() {0xFFFFFFFC, 0x0, 0x4}, 0} + } + } + }) + + Method(_STA, 0x0, NotSerialized) + { + Return(0xf) + } + + Method(_DSM, 0x4, Serialized) + { + If(LEqual(Arg0,ToUUID("B8FEBFE0-BAF8-454b-AECD-49FB91137B21"))) + { + + // Number of fn IDs supported + If(LEqual(Arg2, Zero)) + { + Return(Buffer(One) + { + 0xf + }) + } + + // Pep presence + If(LEqual(Arg2, One)) + { + Store(0x1, PEPP) + Return(0xf) + } + + // Mitigation devices + If(LEqual(Arg2, 0x2)) + { + If(LEqual(Arg1, 0x0)) + { + // Rev0 + Return(DEVS) + } + If(LEqual(Arg1, 0x1)) + { + // Rev1 + Return(DEVX) + } + } + + // Crashdump device data + If(LEqual(Arg2, 0x3)) + { + Store("\\_SB.SDHA", Index(CDMP,0)) + Store(EM1A, Index(CDMP,1)) + Return(CDMP) + } + } + // New UUID for built-in uPEP + If(LEqual(Arg0,ToUUID("C4EB40A0-6CD2-11E2-BCFD-0800200C9A66"))) + { + + // Number of fn IDs supported + If(LEqual(Arg2, Zero)) + { + Return(Buffer(One) + { + 0x7 + }) + } + // LPI device dependencies + If(LEqual(Arg2, 0x1)) + { + Return(DEVY) + } + // Crashdump device data + If(LEqual(Arg2, 0x2)) + { + Store(EM1A, Local0) + Add(Local0, 0x84, Local0) + Store(Local0, Index(DerefOf(Index(DerefOf(Index(DerefOf(Index(DerefOf(Index(BCCD, Zero, )), One, )), Zero, )), Zero, )), 0x4, )) + Return(BCCD) + } + } + + Return(One) + } +} + +// +// eMMC 4.41 +// +Device(SDHA) +{ + Name (_ADR, 0) + Name (_HID, "80860F14") + Name (_CID, "PNP0D40") + Name (_DDN, "Intel(R) eMMC Controller - 80860F14") + Name (_UID, 1) + Name(_DEP, Package(0x1) + { + PEPD + }) + + Name (RBF1, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {45} // eMMC 4.41 IRQ + }) + + Method (_CRS, 0x0, NotSerialized) + { + // Update the Base address for BAR0 of eMMC 4.41 + CreateDwordField(^RBF1, ^BAR0._BAS, B0B1) + CreateDwordField(^RBF1, ^BAR0._LEN, B0L1) + Store(eM0A, B0B1) + Store(eM0L, B0L1) + Return (RBF1) + } + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // SD1D>> 0:eMMC 4.41 enable 1:eMMC 4.41 disable + // + If (LAnd(LEqual(PCIM, 0), LEqual(SD1D, 0))) + { + Return (0xF) + } + Else + { + Return (0x0) + } + } + + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + // + // If not B1, still keep 2 ms w/a + // + If(LLess(SOCS, 0x03)) + { + Sleep(2) + } + } + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + // + // If not B1, still keep 2 ms w/a + // + If(LLess(SOCS, 0x03)) + { + Sleep(2) + } + } + + OperationRegion (KEYS, SystemMemory, eM1A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } + + Method (_DIS, 0x0, NotSerialized) + { + //Adding dummy disable methods for device EMM0 + } + + Device (EMMD) + { + Name (_ADR, 0x00000008) // Slot 0, Function 8 + Method (_RMV, 0, NotSerialized) + { + Return (0x0) + } + } +} + + +// +// eMMC 4.5 +// +Device(SDHD) +{ + Name (_ADR, 0) + Name (_HID, "80860F14") + Name (_CID, "PNP0D40") + Name (_DDN, "Intel(R) eMMC Controller - 80860F14") + Name (_UID, 1) + Name(_DEP, Package(0x1) + { + PEPD + }) + + Name (RBF1, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {44} // eMMC 4.5 IRQ + }) + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBF1, ^BAR0._BAS, B0B1) + CreateDwordField(^RBF1, ^BAR0._LEN, B0L1) + Store(eM0A, B0B1) + Store(eM0L, B0L1) + Return (RBF1) + } + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // HSID>> 0:eMMC 4.5 enable 1:eMMC 4.5 disable + // + If (LAnd(LEqual(PCIM, 0), LEqual(HSID, 0))) + { + Return (0xF) + } + Else + { + Return (0x0) + } + } + + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + // + // If not B1, still keep 2 ms w/a + // + If(LLess(SOCS, 0x03)) + { + Sleep(2) + } + } + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + // + // If not B1, still keep 2 ms w/a + // + If(LLess(SOCS, 0x03)) + { + Sleep(2) + } + } + + OperationRegion (KEYS, SystemMemory, eM1A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } + + Method (_DIS, 0x0, NotSerialized) + { + //Adding dummy disable methods for device EMM0 + } + + Device (EM45) + { + Name (_ADR, 0x00000008) // Slot 0, Function 8 + Method (_RMV, 0, NotSerialized) + { + Return (0x0) + } + } +} + + +// +// SDIO +// +Device(SDHB) +{ + Name (_ADR, 0) + Name (_HID, "INT33BB") + Name (_CID, "PNP0D40") + Name (_DDN, "Intel(R) SDIO Controller - 80860F15") + Name (_UID, 2) + Name (_HRV, 2) + Name(_DEP, Package(0x01) + { + PEPD + }) + Name (PSTS, 0x0) + + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {46} // SDIO IRQ + }) + + Method (_CRS, 0x0, NotSerialized) + { + + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(SI0A, B0BA) + Store(SI0L, B0LN) + Return (RBUF) + } + Method (_STA, 0x0, NotSerialized) + { + If (LLessEqual(STEP, 0x04)) + { + //A stepping + Store(SDMD, _HRV) + } + + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(SI0A, 0), LEqual(SD2D, 1))) + { + Return (0x0) + } + Return (0xF) + } + Method (_DIS, 0x0, NotSerialized) + { + //Adding dummy disable methods for device EMM0 + } + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + + if(LEqual(\_SB.SDHB.PSTS,0x0)) + { + if(LEqual (\_SB.GPO2.AVBL, 1)) + { + Store( 0x01, \_SB.GPO2.WFD3 ) // WL_WIFI_REQ_ON = 1 put the device to normal state + Store( 0x01, \_SB.SDHB.PSTS) // indicates that the device powered ON + } + } + + + } + OperationRegion (KEYS, SystemMemory, SI1A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } + + + Device (BRCM) + { + Name (_ADR, 0x01) //SlotNumber + Function + Name (_DEP, Package() {\_SB.GPO2}) + + Method (_RMV, 0, NotSerialized) + { + Return (0x0) + } + Name (_PRW, Package() {0, 0}) + Name (_S4W, 2) + + Method (_CRS, 0, Serialized) + { + Name (RBUF, ResourceTemplate () + { + Interrupt (ResourceConsumer, Edge, ActiveHigh, ExclusiveAndWake, , , ) {73} + }) + Return (RBUF) + } + + Method (_PS3, 0, NotSerialized) + { + if(LEqual (\_SB.GPO2.AVBL, 1)) + { + Store( 0x00, \_SB.GPO2.WFD3 ) // WL_WIFI_REQ_ON = 0 puts the device in reset state + Store( 0x00, \_SB.SDHB.PSTS) //Indicates that the device is powered off + } + + } + Method (_PS0, 0, NotSerialized) + { + if(LEqual(\_SB.SDHB.PSTS,0x0)) + { + if(LEqual (\_SB.GPO2.AVBL, 1)) + { + Store( 0x01, \_SB.GPO2.WFD3 ) // WL_WIFI_REQ_ON = 1 put the device to normal state + Store( 0x01, \_SB.SDHB.PSTS) // indicates that the device powered ON + } + } + } + } // Device (BRCM) + // + // Secondary Broadcom WIFI function + // + Device(BRC2) + { + Name(_ADR, 0x2) // function 2 + Name(_STA, 0xf) + // + // The device is not removable. This must be a method. + // + Method(_RMV, 0x0, NotSerialized) + { + Return(0x0) + } + + // + // Describe a vendor-defined connection between this device and the + // primary wifi device + // + + Method(_CRS) + { + Name(NAM, Buffer() {"\\_SB.SDHB.BRCM"}) + Name(SPB, Buffer() + { + 0x8E, // SPB Descriptor + 0x18, 0x00, // Length including NAM above + 0x01, // +0x00 SPB Descriptor Revision + 0x00, // +0x01 Resource Source Index + 0xc0, // +0x02 Bus type - vendor defined + 0x02, // +0x03 Consumer + controller initiated + 0x00, 0x00, // +0x04 Type specific flags + 0x01, // +0x06 Type specific revision + 0x00, 0x00 // +0x07 type specific data length + // +0x09 - 0xf bytes for NULL-terminated NAM + // Length = 0x18 + }) + + Name(END, Buffer() {0x79, 0x00}) + Concatenate(SPB, NAM, Local0) + Concatenate(Local0, END, Local1) + Return(Local1) + } + } + +} + +// +// SD Card +// +Device(SDHC) +{ + Name (_ADR, 0) + Name (_HID, "80860F16") + Name (_CID, "PNP0D40") + Name (_DDN, "Intel(R) SD Card Controller - 80860F16") + Name (_UID, 3) + Name(_DEP, Package(0x01) + { + PEPD + }) + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {47} // SD Card IRQ + }) + Method (_CRS, 0x0, NotSerialized) + { + CreateDwordField(^RBUF, ^BAR0._BAS, B0BA) + CreateDwordField(^RBUF, ^BAR0._LEN, B0LN) + Store(SD0A, B0BA) + Store(SD0L, B0LN) + Return (RBUF) + } + Method (_STA, 0x0, NotSerialized) + { + // + // PCIM>> 0:ACPI mode 1:PCI mode + // + If (LEqual(PCIM, 1)) { + Return (0x0) + } + + If (LOr(LEqual(SD0A, 0), LEqual(SD3D, 1))) + { + Return (0x0) + } + Return (0xF) + } + + Method (_PS3, 0, NotSerialized) + { + OR(PSAT, 0x00000003, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + Method (_PS0, 0, NotSerialized) + { + And(PSAT, 0xfffffffC, PSAT) + OR(PSAT, 0X00000000, PSAT) + } + OperationRegion (KEYS, SystemMemory, SD1A, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32 + } + + Device (CARD) + { + Name (_ADR, 0x00000008) + Method(_RMV, 0x0, NotSerialized) + { + // SDRM = 0 non-removable; + If (LEqual(SDRM, 0)) + { + Return (0) + } + + Return (1) + } + } + +} + diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchSmb.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchSmb.asl new file mode 100644 index 0000000000..42ecbe296f --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchSmb.asl @@ -0,0 +1,839 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + + +// Define various SMBus PCI Configuration Space Registers. + +OperationRegion(SMBP,PCI_Config,0x40,0xC0) +Field(SMBP,DWordAcc,NoLock,Preserve) +{ + , 2, + I2CE, 1 +} + +// SMBus Send Byte - This function will write a single byte of +// data to a specific Slave Device per SMBus Send Byte Protocol. +// Arg0 = Address +// Arg1 = Data +// Return: Success = 1 +// Failure = 0 + + Method(SSXB,2,Serialized) +{ + OperationRegion(SMPB,PCI_Config,0x20,4) + Field(SMPB,DWordAcc,NoLock,Preserve) + { + , 5, + SBAR, 11 + } + + // Define various SMBus IO Mapped Registers. + + OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10) + Field(SMBI,ByteAcc,NoLock,Preserve) + { + HSTS, 8, // 0 - Host Status Register + Offset(0x02), + HCON, 8, // 2 - Host Control + HCOM, 8, // 3 - Host Command + TXSA, 8, // 4 - Transmit Slave Address + DAT0, 8, // 5 - Host Data 0 + DAT1, 8, // 6 - Host Data 1 + HBDR, 8, // 7 - Host Block Data + PECR, 8, // 8 - Packer Error Check + RXSA, 8, // 9 - Receive Slave Address + SDAT, 16, // A - Slave Data + } + + // Step 1: Confirm the ICHx SMBus is ready to perform + // communication. + + If(STRT()) + { + Return(0) + } + + // Step 2: Initiate a Send Byte. + + Store(0,I2CE) // Ensure SMbus Mode. + Store(0xBF,HSTS) // Clear all but INUSE_STS. + Store(Arg0,TXSA) // Write Address in TXSA. + Store(Arg1,HCOM) // Data in HCOM. + + // Set the SMBus Host control register to 0x48. + // Bit 7: = 0 = reserved + // Bit 6: = 1 = start + // Bit 5: = 0 = disregard, I2C related bit + // Bits 4:2: = 001 = Byte Protocol + // Bit 1: = 0 = Normal Function + // Bit 0: = 0 = Disable interrupt generation + + Store(0x48,HCON) + + // Step 3: Exit the Method correctly. + + If(COMP) + { + Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others.. + Return(1) // Return Success. + } + + Return(0) +} + +// SMBus Receive Byte - This function will write a single byte +// of data to a specific Slave Device per SMBus Receive Byte +// Protocol. +// Arg0 = Address +// Return: Success = Byte-Size Value +// Failure = Word-Size Value = FFFFh. + +Method(SRXB,1,Serialized) +{ + OperationRegion(SMPB,PCI_Config,0x20,4) + Field(SMPB,DWordAcc,NoLock,Preserve) + { + , 5, + SBAR, 11 + } + + // Define various SMBus IO Mapped Registers. + + OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10) + Field(SMBI,ByteAcc,NoLock,Preserve) + { + HSTS, 8, // 0 - Host Status Register + Offset(0x02), + HCON, 8, // 2 - Host Control + HCOM, 8, // 3 - Host Command + TXSA, 8, // 4 - Transmit Slave Address + DAT0, 8, // 5 - Host Data 0 + DAT1, 8, // 6 - Host Data 1 + HBDR, 8, // 7 - Host Block Data + PECR, 8, // 8 - Packer Error Check + RXSA, 8, // 9 - Receive Slave Address + SDAT, 16, // A - Slave Data + } + // Step 1: Confirm the ICHx SMBus is ready to perform + // communication. + + If(STRT()) + { + Return(0xFFFF) + } + + // Step 2: Initiate a Receive Byte. + + Store(0,I2CE) // Ensure SMbus Mode. + Store(0xBF,HSTS) // Clear all but INUSE_STS. + Store(Or(Arg0,1),TXSA) // Read Address in TXSA. + + // Set the SMBus Host control register to 0x48. + // Bit 7: = 0 = reserved + // Bit 6: = 1 = start + // Bit 5: = 0 = disregard, I2C related bit + // Bits 4:2: = 001 = Byte Protocol + // Bit 1: = 0 = Normal Function + // Bit 0: = 0 = Disable interrupt generation + + Store(0x44,HCON) + + // Step 3: Exit the Method correctly. + + If(COMP) + { + Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others.. + Return(DAT0) // Return Success. + } + + Return(0xFFFF) // Return Failure. +} + +// SMBus Write Byte - This function will write a single byte +// of data to a specific Slave Device per SMBus Write Byte +// Protocol. +// Arg0 = Address +// Arg1 = Command +// Arg2 = Data +// Return: Success = 1 +// Failure = 0 + +Method(SWRB,3,Serialized) +{ + OperationRegion(SMPB,PCI_Config,0x20,4) + Field(SMPB,DWordAcc,NoLock,Preserve) + { + , 5, + SBAR, 11 + } + + // Define various SMBus IO Mapped Registers. + + OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10) + Field(SMBI,ByteAcc,NoLock,Preserve) + { + HSTS, 8, // 0 - Host Status Register + Offset(0x02), + HCON, 8, // 2 - Host Control + HCOM, 8, // 3 - Host Command + TXSA, 8, // 4 - Transmit Slave Address + DAT0, 8, // 5 - Host Data 0 + DAT1, 8, // 6 - Host Data 1 + HBDR, 8, // 7 - Host Block Data + PECR, 8, // 8 - Packer Error Check + RXSA, 8, // 9 - Receive Slave Address + SDAT, 16, // A - Slave Data + } + // Step 1: Confirm the ICHx SMBus is ready to perform communication. + + If(STRT()) + { + Return(0) + } + + // Step 2: Initiate a Write Byte. + + Store(0,I2CE) // Ensure SMbus Mode. + Store(0xBF,HSTS) // Clear all but INUSE_STS. + Store(Arg0,TXSA) // Write Address in TXSA. + Store(Arg1,HCOM) // Command in HCOM. + Store(Arg2,DAT0) // Data in DAT0. + + // Set the SMBus Host control register to 0x48. + // Bit 7: = 0 = reserved + // Bit 6: = 1 = start + // Bit 5: = 0 = disregard, I2C related bit + // Bits 4:2: = 010 = Byte Data Protocol + // Bit 1: = 0 = Normal Function + // Bit 0: = 0 = Disable interrupt generation + + Store(0x48,HCON) + + // Step 3: Exit the Method correctly. + + If(COMP) + { + Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others.. + Return(1) // Return Success. + } + + Return(0) // Return Failure. +} + +// SMBus Read Byte - This function will read a single byte of data +// from a specific slave device per SMBus Read Byte Protocol. +// Arg0 = Address +// Arg1 = Command +// Return: Success = Byte-Size Value +// Failure = Word-Size Value + +Method(SRDB,2,Serialized) +{ + OperationRegion(SMPB,PCI_Config,0x20,4) + Field(SMPB,DWordAcc,NoLock,Preserve) + { + , 5, + SBAR, 11 + } + + // Define various SMBus IO Mapped Registers. + + OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10) + Field(SMBI,ByteAcc,NoLock,Preserve) + { + HSTS, 8, // 0 - Host Status Register + Offset(0x02), + HCON, 8, // 2 - Host Control + HCOM, 8, // 3 - Host Command + TXSA, 8, // 4 - Transmit Slave Address + DAT0, 8, // 5 - Host Data 0 + DAT1, 8, // 6 - Host Data 1 + HBDR, 8, // 7 - Host Block Data + PECR, 8, // 8 - Packer Error Check + RXSA, 8, // 9 - Receive Slave Address + SDAT, 16, // A - Slave Data + } + // Step 1: Confirm the ICHx SMBus is ready to perform communication. + + If(STRT()) + { + Return(0xFFFF) + } + + // Step 2: Initiate a Read Byte. + + Store(0,I2CE) // Ensure SMbus Mode. + Store(0xBF,HSTS) // Clear all but INUSE_STS. + Store(Or(Arg0,1),TXSA) // Read Address in TXSA. + Store(Arg1,HCOM) // Command in HCOM. + + // Set the SMBus Host control register to 0x48. + // Bit 7: = 0 = reserved + // Bit 6: = 1 = start + // Bit 5: = 0 = disregard, I2C related bit + // Bits 4:2: = 010 = Byte Data Protocol + // Bit 1: = 0 = Normal Function + // Bit 0: = 0 = Disable interrupt generation + + Store(0x48,HCON) + + // Step 3: Exit the Method correctly. + + If(COMP) + { + Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others.. + Return(DAT0) // Return Success. + } + + Return(0xFFFF) // Return Failure. +} + +// SMBus Write Word - This function will write a single word +// of data to a specific Slave Device per SMBus Write Word +// Protocol. +// Arg0 = Address +// Arg1 = Command +// Arg2 = Data (16 bits in size) +// Return: Success = 1 +// Failure = 0 + +Method(SWRW,3,Serialized) +{ + OperationRegion(SMPB,PCI_Config,0x20,4) + Field(SMPB,DWordAcc,NoLock,Preserve) + { + , 5, + SBAR, 11 + } + + // Define various SMBus IO Mapped Registers. + + OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10) + Field(SMBI,ByteAcc,NoLock,Preserve) + { + HSTS, 8, // 0 - Host Status Register + Offset(0x02), + HCON, 8, // 2 - Host Control + HCOM, 8, // 3 - Host Command + TXSA, 8, // 4 - Transmit Slave Address + DAT0, 8, // 5 - Host Data 0 + DAT1, 8, // 6 - Host Data 1 + HBDR, 8, // 7 - Host Block Data + PECR, 8, // 8 - Packer Error Check + RXSA, 8, // 9 - Receive Slave Address + SDAT, 16, // A - Slave Data + } + // Step 1: Confirm the ICHx SMBus is ready to perform communication. + + If(STRT()) + { + Return(0) + } + + // Step 2: Initiate a Write Word. + + Store(0,I2CE) // Ensure SMbus Mode. + Store(0xBF,HSTS) // Clear all but INUSE_STS. + Store(Arg0,TXSA) // Write Address in TXSA. + Store(Arg1,HCOM) // Command in HCOM. + And(Arg2,0xFF,DAT1) // Low byte Data in DAT1. + And(ShiftRight(Arg2,8),0xFF,DAT0) // High byte Data in DAT0. + + // Set the SMBus Host control register to 0x4C. + // Bit 7: = 0 = reserved + // Bit 6: = 1 = start + // Bit 5: = 0 = disregard, I2C related bit + // Bits 4:2: = 011 = Word Data Protocol + // Bit 1: = 0 = Normal Function + // Bit 0: = 0 = Disable interrupt generation + + Store(0x4C,HCON) + + // Step 3: Exit the Method correctly. + + If(COMP()) + { + Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others. + Return(1) // Return Success. + } + + Return(0) // Return Failure. +} + +// SMBus Read Word - This function will read a single byte of data +// from a specific slave device per SMBus Read Word Protocol. +// Arg0 = Address +// Arg1 = Command +// Return: Success = Word-Size Value +// Failure = Dword-Size Value + +Method(SRDW,2,Serialized) +{ + OperationRegion(SMPB,PCI_Config,0x20,4) + Field(SMPB,DWordAcc,NoLock,Preserve) + { + , 5, + SBAR, 11 + } + + // Define various SMBus IO Mapped Registers. + + OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10) + Field(SMBI,ByteAcc,NoLock,Preserve) + { + HSTS, 8, // 0 - Host Status Register + Offset(0x02), + HCON, 8, // 2 - Host Control + HCOM, 8, // 3 - Host Command + TXSA, 8, // 4 - Transmit Slave Address + DAT0, 8, // 5 - Host Data 0 + DAT1, 8, // 6 - Host Data 1 + HBDR, 8, // 7 - Host Block Data + PECR, 8, // 8 - Packer Error Check + RXSA, 8, // 9 - Receive Slave Address + SDAT, 16, // A - Slave Data + } + // Step 1: Confirm the ICHx SMBus is ready to perform communication. + + If(STRT()) + { + Return(0xFFFF) + } + + // Step 2: Initiate a Read Word. + + Store(0,I2CE) // Ensure SMbus Mode. + Store(0xBF,HSTS) // Clear all but INUSE_STS. + Store(Or(Arg0,1),TXSA) // Read Address in TXSA. + Store(Arg1,HCOM) // Command in HCOM. + + // Set the SMBus Host control register to 0x4C. + // Bit 7: = 0 = reserved + // Bit 6: = 1 = start + // Bit 5: = 0 = disregard, I2C related bit + // Bits 4:2: = 011 = Word Data Protocol + // Bit 1: = 0 = Normal Function + // Bit 0: = 0 = Disable interrupt generation + + Store(0x4C,HCON) + + // Step 3: Exit the Method correctly. + + If(COMP()) + { + Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others. + Return(Or(ShiftLeft(DAT0,8),DAT1)) // Return Success. + } + + Return(0xFFFFFFFF) // Return Failure. +} + +// SMBus Block Write - This function will write an entire block of data +// to a specific slave device per SMBus Block Write Protocol. +// Arg0 = Address +// Arg1 = Command +// Arg2 = Buffer of Data to Write +// Arg3 = 1 = I2C Block Write, 0 = SMBus Block Write +// Return: Success = 1 +// Failure = 0 + +Method(SBLW,4,Serialized) +{ + OperationRegion(SMPB,PCI_Config,0x20,4) + Field(SMPB,DWordAcc,NoLock,Preserve) + { + , 5, + SBAR, 11 + } + + // Define various SMBus IO Mapped Registers. + + OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10) + Field(SMBI,ByteAcc,NoLock,Preserve) + { + HSTS, 8, // 0 - Host Status Register + Offset(0x02), + HCON, 8, // 2 - Host Control + HCOM, 8, // 3 - Host Command + TXSA, 8, // 4 - Transmit Slave Address + DAT0, 8, // 5 - Host Data 0 + DAT1, 8, // 6 - Host Data 1 + HBDR, 8, // 7 - Host Block Data + PECR, 8, // 8 - Packer Error Check + RXSA, 8, // 9 - Receive Slave Address + SDAT, 16, // A - Slave Data + } + // Step 1: Confirm the ICHx SMBus is ready to perform communication. + + If(STRT()) + { + Return(0) + } + + // Step 2: Initiate a Block Write. + + Store(Arg3,I2CE) // Select the proper protocol. + Store(0xBF,HSTS) // Clear all but INUSE_STS. + Store(Arg0,TXSA) // Write Address in TXSA. + Store(Arg1,HCOM) // Command in HCOM. + Store(Sizeof(Arg2),DAT0) // Count in DAT0. + Store(0,Local1) // Init Pointer to Buffer. + Store(DerefOf(Index(Arg2,0)),HBDR) // First Byte in HBD Register. + + // Set the SMBus Host control register to 0x48. + // Bit 7: = 0 = reserved + // Bit 6: = 1 = start + // Bit 5: = 0 = disregard, I2C related bit + // Bits 4:2: = 101 = Block Protocol + // Bit 1: = 0 = Normal Function + // Bit 0: = 0 = Disable interrupt generation + + Store(0x54,HCON) + + // Step 3: Send the entire Block of Data. + + While(LGreater(Sizeof(Arg2),Local1)) + { + // Wait up to 200ms for Host Status to get set. + + Store(4000,Local0) // 4000 * 50us = 200ms. + + While(LAnd(LNot(And(HSTS,0x80)),Local0)) + { + Decrement(Local0) // Decrement Count. + Stall(50) // Delay = 50us. + } + + If(LNot(Local0)) // Timeout? + { + KILL() // Yes. Kill Communication. + Return(0) // Return failure. + } + + Store(0x80,HSTS) // Clear Host Status. + Increment(Local1) // Point to Next Byte. + + // Place next byte in HBDR if last byte has not been sent. + + If(LGreater(Sizeof(Arg2),Local1)) + { + Store(DerefOf(Index(Arg2,Local1)),HBDR) + } + } + + // Step 4: Exit the Method correctly. + + If(COMP()) + { + Or(HSTS,0xFF,HSTS) // Clear all status bits. + Return(1) // Return Success. + } + + Return(0) // Return Failure. +} + +// SMBus Block Read - This function will read a block of data from +// a specific slave device per SMBus Block Read Protocol. +// Arg0 = Address +// Arg1 = Command +// Arg2 = 1 = I2C Block Write, 0 = SMBus Block Write +// Return: Success = Data Buffer (First Byte = length) +// Failure = 0 + +Method(SBLR,3,Serialized) +{ + OperationRegion(SMPB,PCI_Config,0x20,4) + Field(SMPB,DWordAcc,NoLock,Preserve) + { + , 5, + SBAR, 11 + } + + // Define various SMBus IO Mapped Registers. + + OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10) + Field(SMBI,ByteAcc,NoLock,Preserve) + { + HSTS, 8, // 0 - Host Status Register + Offset(0x02), + HCON, 8, // 2 - Host Control + HCOM, 8, // 3 - Host Command + TXSA, 8, // 4 - Transmit Slave Address + DAT0, 8, // 5 - Host Data 0 + DAT1, 8, // 6 - Host Data 1 + HBDR, 8, // 7 - Host Block Data + PECR, 8, // 8 - Packer Error Check + RXSA, 8, // 9 - Receive Slave Address + SDAT, 16, // A - Slave Data + } + Name(TBUF, Buffer(256) {}) + + // Step 1: Confirm the ICHx SMBus is ready to perform communication. + + If(STRT()) + { + Return(0) + } + + // Step 2: Initiate a Block Read. + + Store(Arg2,I2CE) // Select the proper protocol. + Store(0xBF,HSTS) // Clear all but INUSE_STS. + Store(Or(Arg0,1),TXSA) // Read Address in TXSA. + Store(Arg1,HCOM) // Command in HCOM. + + // Set the SMBus Host control register to 0x48. + // Bit 7: = 0 = reserved + // Bit 6: = 1 = start + // Bit 5: = 0 = disregard, I2C related bit + // Bits 4:2: = 101 = Block Protocol + // Bit 1: = 0 = Normal Function + // Bit 0: = 0 = Disable interrupt generation + + Store(0x54,HCON) + + // Step 3: Wait up to 200ms to get the Data Count. + + Store(4000,Local0) // 4000 * 50us = 200ms. + + While(LAnd(LNot(And(HSTS,0x80)),Local0)) + { + Decrement(Local0) // Decrement Count. + Stall(50) // Delay = 50us. + } + + If(LNot(Local0)) // Timeout? + { + KILL() // Yes. Kill Communication. + Return(0) // Return failure. + } + + Store(DAT0,Index(TBUF,0)) // Get the Data Count. + Store(0x80,HSTS) // Clear Host Status. + Store(1,Local1) // Local1 = Buffer Pointer. + + // Step 4: Get the Block Data and store it. + + While(LLess(Local1,DerefOf(Index(TBUF,0)))) + { + // Wait up to 200ms for Host Status to get set. + + Store(4000,Local0) // 4000 * 50us = 200ms. + + While(LAnd(LNot(And(HSTS,0x80)),Local0)) + { + Decrement(Local0) // Decrement Count. + Stall(50) // Delay = 50us. + } + + If(LNot(Local0)) // Timeout? + { + KILL() // Yes. Kill Communication. + Return(0) // Return failure. + } + + Store(HBDR,Index(TBUF,Local1)) // Place into Buffer. + Store(0x80,HSTS) // Clear Host Status. + Increment(Local1) + } + + // Step 5: Exit the Method correctly. + + If(COMP()) + { + Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others. + Return(TBUF) // Return Success. + } + + Return(0) // Return Failure. +} + + +// SMBus Start Check +// Return: Success = 0 +// Failure = 1 + +Method(STRT,0,Serialized) +{ + OperationRegion(SMPB,PCI_Config,0x20,4) + Field(SMPB,DWordAcc,NoLock,Preserve) + { + , 5, + SBAR, 11 + } + + // Define various SMBus IO Mapped Registers. + + OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10) + Field(SMBI,ByteAcc,NoLock,Preserve) + { + HSTS, 8, // 0 - Host Status Register + Offset(0x02), + HCON, 8, // 2 - Host Control + HCOM, 8, // 3 - Host Command + TXSA, 8, // 4 - Transmit Slave Address + DAT0, 8, // 5 - Host Data 0 + DAT1, 8, // 6 - Host Data 1 + HBDR, 8, // 7 - Host Block Data + PECR, 8, // 8 - Packer Error Check + RXSA, 8, // 9 - Receive Slave Address + SDAT, 16, // A - Slave Data + } + // Wait up to 200ms to confirm the SMBus Semaphore has been + // released (In Use Status = 0). Note that the Sleep time may take + // longer as the This function will yield the Processor such that it + // may perform different tasks during the delay. + + Store(200,Local0) // 200 * 1ms = 200ms. + + While(Local0) + { + If(And(HSTS,0x40)) // In Use Set? + { + Decrement(Local0) // Yes. Decrement Count. + Sleep(1) // Delay = 1ms. + If(LEqual(Local0,0)) // Count = 0? + { + Return(1) // Return failure. + } + } + Else + { + Store(0,Local0) // In Use Clear. Continue. + } + } + + // In Use Status = 0 during last read, which will make subsequent + // reads return In Use Status = 1 until software clears it. All + // software using ICHx SMBus should check this bit before initiating + // any SMBus communication. + + // Wait up to 200ms to confirm the Host Interface is + // not processing a command. + + Store(4000,Local0) // 4000 * 50us = 200ms. + + While(Local0) + { + If(And(HSTS,0x01)) // Host Busy Set? + { + Decrement(Local0) // Decrement Count. + Stall(50) // Delay = 50us. + If(LEqual(Local0,0)) // Count = 0? + { + KILL() // Yes. Kill Communication. + } + } + Else + { + Return(0) + } + } + + Return(1) // Timeout. Return failure. +} + +// SMBus Completion Check +// Return: Success = 1 +// Failure = 0 + +Method(COMP,0,Serialized) +{ + OperationRegion(SMPB,PCI_Config,0x20,4) + Field(SMPB,DWordAcc,NoLock,Preserve) + { + , 5, + SBAR, 11 + } + + // Define various SMBus IO Mapped Registers. + + OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10) + Field(SMBI,ByteAcc,NoLock,Preserve) + { + HSTS, 8, // 0 - Host Status Register + Offset(0x02), + HCON, 8, // 2 - Host Control + HCOM, 8, // 3 - Host Command + TXSA, 8, // 4 - Transmit Slave Address + DAT0, 8, // 5 - Host Data 0 + DAT1, 8, // 6 - Host Data 1 + HBDR, 8, // 7 - Host Block Data + PECR, 8, // 8 - Packer Error Check + RXSA, 8, // 9 - Receive Slave Address + SDAT, 16, // A - Slave Data + } + // Wait for up to 200ms for the Completion Command + // Status to get set. + + Store(4000,Local0) // 4000 * 50us = 200ms. + + While(Local0) + { + If(And(HSTS,0x02)) // Completion Status Set? + { + Return(1) // Yes. We are done. + } + Else + { + Decrement(Local0) // Decrement Count. + Stall(50) // Delay 50us. + If(LEqual(Local0,0)) // Count = 0? + { + KILL() // Yes. Kill Communication. + } + } + } + + Return(0) // Timeout. Return Failure. +} + +// SMBus Kill Command + +Method(KILL,0,Serialized) +{ + OperationRegion(SMPB,PCI_Config,0x20,4) + Field(SMPB,DWordAcc,NoLock,Preserve) + { + , 5, + SBAR, 11 + } + + // Define various SMBus IO Mapped Registers. + + OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10) + Field(SMBI,ByteAcc,NoLock,Preserve) + { + HSTS, 8, // 0 - Host Status Register + Offset(0x02), + HCON, 8, // 2 - Host Control + HCOM, 8, // 3 - Host Command + TXSA, 8, // 4 - Transmit Slave Address + DAT0, 8, // 5 - Host Data 0 + DAT1, 8, // 6 - Host Data 1 + HBDR, 8, // 7 - Host Block Data + PECR, 8, // 8 - Packer Error Check + RXSA, 8, // 9 - Receive Slave Address + SDAT, 16, // A - Slave Data + } + Or(HCON,0x02,HCON) // Yes. Send Kill command. + Or(HSTS,0xFF,HSTS) // Clear all status. +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchXhci.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchXhci.asl new file mode 100644 index 0000000000..696a5411d5 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PchXhci.asl @@ -0,0 +1,385 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Haswell *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + +//scope is \_SB.PCI0.XHC +Device(XHC1) +{ + Name(_ADR, 0x00140000) //Device 20, Function 0 + + //When it is in Host mode, USH core is connected to USB3 microAB(USB3 P1 and USB2 P0) + Name (_DDN, "Baytrail XHCI controller (CCG core/Host only)" ) + + Method(XDEP, 0) + { + If(LEqual(OSYS,2013)) + { + Name(_DEP, Package(0x1) + { + PEPD + }) + } + } + + Name (_STR, Unicode ("Baytrail XHCI controller (CCG core/Host only)")) + Name(_PRW, Package() {0xD,4}) + + Method(_PSW,1) + { + If (LAnd (PMES, PMEE)) { + Store (0, PMEE) + Store (1, PMES) + } + } + + OperationRegion (PMEB, PCI_Config, 0x74, 0x04) // Power Management Control/Status + Field (PMEB, WordAcc, NoLock, Preserve) + { + , 8, + PMEE, 1, //bit8 PME_En + , 6, + PMES, 1 //bit15 PME_Status + } + + Method(_STA, 0) + { + If(LNotEqual(XHCI, 0)) //NVS variable controls present of XHCI controller + { + Return (0xF) + } Else + { + Return (0x0) + } + } + + OperationRegion(XPRT,PCI_Config,0xD0,0x10) + Field(XPRT,DWordAcc,NoLock,Preserve) //usbx_top.doc.xml + { + PR2, 32, //bit[8:0] USB2HCSEL + PR2M, 32, //bit[8:0] USB2HCSELM + PR3, 32, //bit[3:0] USB3SSEN + PR3M, 32 //bit[3:0] USB3SSENM + } + + Device(RHUB) + { + Name(_ADR, Zero) //address 0 is reserved for root hub + + // + // Super Speed Ports - must match _UPC declarations of the coresponding Full Speed Ports. + // Paired with Port 1 + Device(SSP1) + { + Name(_ADR, 0x07) + + Method(_UPC,0,Serialized) + { + Name(UPCP, Package() + { + 0xFF, // Port is connectable if non-zero + 0x06, // USB3 uAB connector + 0x00, + 0x00 + }) + Return(UPCP) + } + + Method(_PLD,0,Serialized) + { + Name(PLDP, Package() //pls check ACPI 5.0 section 6.1.8 + { + Buffer(0x14) + { + //31:0 - Bit[6:0]=2 revision is 0x2, Bit[7]=1 Ignore Color Bit[31:8]=0 RGB color is ignored + 0x82, 0x00, 0x00, 0x00, + //63:32 - Bit[47:32]=0 width: 0x0000 Bit[63:48]=0 Height:0x0000 + 0x00, 0x00, 0x00, 0x00, + //95:64 - bit[66:64]=b'011 visiable/docking/no lid bit[69:67]=b'001 bottom panel bit[71:70]=b'01 Center bit[73:72]=b'01 Center + // bit[77:74]=6 Horizontal Trapezoid bit[78]=0 bit[86:79]=0 bit[94:87]='0 no group info' bit[95]=0 not a bay + 0x4B, 0x19, 0x00, 0x00, + //127:96 -bit[96]=1 Ejectable bit[97]=1 OSPM Ejection required Bit[105:98]=0 no Cabinet Number + // bit[113:106]=0 no Card cage Number bit[114]=0 no reference shape Bit[118:115]=0 no rotation Bit[123:119]=0 no order + 0x03, 0x00, 0x00, 0x00, + //159:128 Vert. and Horiz. Offsets not supplied + 0xFF, 0xFF, 0xFF, 0xFF + } + }) + Return (PLDP) + } + } + // + // High Speed Ports + // pair port with port 7 (SS) + // The UPC declarations for LS/FS/HS and SS ports that are paired to form a USB3.0 compatible connector. + // A "pair" is defined by two ports that declare _PLDs with identical Panel, Vertical Position, Horizontal Postion, Shape, Group Orientation + // and Group Token + Device(HS01) + { + Name(_ADR, 0x01) + + Method(_UPC,0,Serialized) + { + Name(UPCP, Package() { 0xFF,0x06,0x00,0x00 }) + Return(UPCP) + } + + Method(_PLD,0,Serialized) + { + Name(PLDP, Package() //pls check ACPI 5.0 section 6.1.8 + { + Buffer(0x14) + { + //31:0 - Bit[6:0]=2 revision is 0x2, Bit[7]=1 Ignore Color Bit[31:8]=0 RGB color is ignored + 0x82, 0x00, 0x00, 0x00, + //63:32 - Bit[47:32]=0 width: 0x0000 Bit[63:48]=0 Height:0x0000 + 0x00, 0x00, 0x00, 0x00, + //95:64 - bit[66:64]=b'011 visiable/docking/no lid bit[69:67]=b'001 bottom panel bit[71:70]=b'01 Center bit[73:72]=b'01 Center + // bit[77:74]=6 Horizontal Trapezoid bit[78]=0 bit[86:79]=0 bit[94:87]='0 no group info' bit[95]=0 not a bay + 0x4B, 0x19, 0x00, 0x00, + //127:96 -bit[96]=1 Ejectable bit[97]=1 OSPM Ejection required Bit[105:98]=0 no Cabinet Number + // bit[113:106]=0 no Card cage Number bit[114]=0 no reference shape Bit[118:115]=0 no rotation Bit[123:119]=0 no order + 0x03, 0x00, 0x00, 0x00, + //159:128 Vert. and Horiz. Offsets not supplied + 0xFF, 0xFF, 0xFF, 0xFF + } + }) + Return (PLDP) + } + }//end of HS01 + + // USB2 Type-A/USB2 only + // EHCI debug capable + Device(HS02) + { + Name(_ADR, 0x02) // 0 is for root hub so physical port index starts from 1 (it is port1 in schematic) + + Method(_UPC,0,Serialized) + { + Name(UPCP, Package() + { + 0xFF, // connectable + 0xFF, // + 0x00, + 0x00 + }) + + Return(UPCP) + } + + Method(_PLD,0,Serialized) + { + Name(PLDP, Package() + { + Buffer(0x14) + { + //31:0 - Bit[6:0]=2 revision is 0x2, Bit[7]=1 Ignore Color Bit[31:8]=0 RGB color is ignored + 0x82, 0x00, 0x00, 0x00, + //63:32 - Bit[47:32]=0 width: 0x0000 Bit[63:48]=0 Height:0x0000 + 0x00, 0x00, 0x00, 0x00, + //95:64 - bit[66:64]=b'000 not visiable/no docking/no lid bit[69:67]=b'000 top bit[71:70]=b'01 Center bit[73:72]=b'00 Left + // bit[77:74]=2 Square bit[78]=0 bit[86:79]=0 bit[94:87]='0 no group info' bit[95]=0 not a bay + 0x40, 0x08, 0x00, 0x00, + //127:96 -bit[96]=0 not Ejectable bit[97]=0 no OSPM Ejection required Bit[105:98]=0 no Cabinet Number + // bit[113:106]=0 no Card cage Number bit[114]=0 no reference shape Bit[118:115]=0 no rotation Bit[123:119]=0 no order + 0x00, 0x00, 0x00, 0x00, + //159:128 Vert. and Horiz. Offsets not supplied + 0xFF, 0xFF, 0xFF, 0xFF + } + }) + + Return (PLDP) + } + }//end of HS02 + // high speed port 3 + Device(HS03) + { + Name(_ADR, 0x03) + + Method(_UPC,0,Serialized) + { + Name(UPCP, Package() + { + 0xFF, // connectable + 0xFF, + 0x00, + 0x00 + }) + + Return(UPCP) + } + + Method(_RMV, 0) // for XHCICV debug purpose + { + Return(0x0) + } + + Method(_PLD,0,Serialized) + { + Name(PLDP, Package() + { + Buffer(0x14) + { + //31:0 - Bit[6:0]=2 revision is 0x2, Bit[7]=1 Ignore Color Bit[31:8]=0 RGB color is ignored + 0x82, 0x00, 0x00, 0x00, + //63:32 - Bit[47:32]=0 width: 0x0000 Bit[63:48]=0 Height:0x0000 + 0x00, 0x00, 0x00, 0x00, + //95:64 - bit[66:64]=b'000 not Visible/no docking/no lid bit[69:67]=6 (b'110) unknown(Vertical Position and Horizontal Position will be ignored) + // bit[71:70]=b'00 Vertical Position ignore bit[73:72]=b'00 Horizontal Position ignore + // bit[77:74]=2 Square bit[78]=0 bit[86:79]=0 bit[94:87]='0 no group info' bit[95]=0 not a bay + 0x30, 0x08, 0x00, 0x00, + //127:96 -bit[96]=0 not Ejectable bit[97]=0 OSPM Ejection not required Bit[105:98]=0 no Cabinet Number + // bit[113:106]=0 no Card cage Number bit[114]=0 no reference shape Bit[118:115]=0 no rotation Bit[123:119]=0 no order + 0x00, 0x00, 0x00, 0x00, + //159:128 Vert. and Horiz. Offsets not supplied + 0xFF, 0xFF, 0xFF, 0xFF + } + }) + Return (PLDP) + } + } + + Device(HS04) + { + Name(_ADR, 0x04) + + Method(_UPC,0,Serialized) + { + Name(UPCP, Package() + { + 0xFF, //connectable + 0xFF, //Proprietary connector (FPC connector) + 0x00, + 0x00 + }) + + Return(UPCP) + } + Method(_PLD,0,Serialized) + { + Name(PLDP, Package() + { + Buffer(0x14) + { + //31:0 - Bit[6:0]=2 revision is 0x2, Bit[7]=1 Ignore Color Bit[31:8]=0 RGB color is ignored + 0x82, 0x00, 0x00, 0x00, + //63:32 - Bit[47:32]=0 width: 0x0000 Bit[63:48]=0 Height:0x0000 + 0x00, 0x00, 0x00, 0x00, + //95:64 - bit[66:64]=b'000 not Visible/no docking/no lid bit[69:67]=6 (b'110) unknown(Vertical Position and Horizontal Position will be ignored) + // bit[71:70]=b'00 Vertical Position ignore bit[73:72]=b'00 Horizontal Position ignore + // bit[77:74]=2 Square bit[78]=0 bit[86:79]=0 bit[94:87]='0 no group info' bit[95]=0 not a bay + 0x30, 0x08, 0x00, 0x00, + //127:96 -bit[96]=0 not Ejectable bit[97]=0 OSPM Ejection not required Bit[105:98]=0 no Cabinet Number + // bit[113:106]=0 no Card cage Number bit[114]=0 no reference shape Bit[118:115]=0 no rotation Bit[123:119]=0 no order + 0x00, 0x00, 0x00, 0x00, + //159:128 Vert. and Horiz. Offsets not supplied + 0xFF, 0xFF, 0xFF, 0xFF + } + }) + + Return (PLDP) + } + } + + + Device(HSC1) // USB2 HSIC 01 + { + Name(_ADR, 0x05) + + Method(_UPC,0,Serialized) + { + Name(UPCP, Package() + { + 0xFF, //connectable + 0xFF, //Proprietary connector (FPC connector) + 0x00, + 0x00 + }) + + Return(UPCP) + } + Method(_PLD,0,Serialized) + { + Name(PLDP, Package() + { + Buffer(0x14) + { + //31:0 - Bit[6:0]=2 revision is 0x2, Bit[7]=1 Ignore Color Bit[31:8]=0 RGB color is ignored + 0x82, 0x00, 0x00, 0x00, + //63:32 - Bit[47:32]=0 width: 0x0000 Bit[63:48]=0 Height:0x0000 + 0x00, 0x00, 0x00, 0x00, + //95:64 - bit[66:64]=b'000 not Visible/no docking/no lid bit[69:67]=6 (b'110) unknown(Vertical Position and Horizontal Position will be ignored) + // bit[71:70]=b'00 Vertical Position ignore bit[73:72]=b'00 Horizontal Position ignore + // bit[77:74]=2 Square bit[78]=0 bit[86:79]=0 bit[94:87]='0 no group info' bit[95]=0 not a bay + 0x30, 0x08, 0x00, 0x00, + //127:96 -bit[96]=0 not Ejectable bit[97]=0 OSPM Ejection not required Bit[105:98]=0 no Cabinet Number + // bit[113:106]=0 no Card cage Number bit[114]=0 no reference shape Bit[118:115]=0 no rotation Bit[123:119]=0 no order + 0x00, 0x00, 0x00, 0x00, + //159:128 Vert. and Horiz. Offsets not supplied + 0xFF, 0xFF, 0xFF, 0xFF + } + }) + Return (PLDP) + } + } + + Device(HSC2) // USB2 HSIC 02 + { + Name(_ADR, 0x06) + + Method(_UPC,0,Serialized) + { + Name(UPCP, Package() + { + 0xFF, //connectable + 0xFF, //Proprietary connector (FPC connector) + 0x00, + 0x00 + }) + + Return(UPCP) + } + Method(_PLD,0,Serialized) + { + Name(PLDP, Package() + { + Buffer(0x14) + { + //31:0 - Bit[6:0]=2 revision is 0x2, Bit[7]=1 Ignore Color Bit[31:8]=0 RGB color is ignored + 0x82, 0x00, 0x00, 0x00, + //63:32 - Bit[47:32]=0 width: 0x0000 Bit[63:48]=0 Height:0x0000 + 0x00, 0x00, 0x00, 0x00, + //95:64 - bit[66:64]=b'000 not Visible/no docking/no lid bit[69:67]=6 (b'110) unknown(Vertical Position and Horizontal Position will be ignored) + // bit[71:70]=b'00 Vertical Position ignore bit[73:72]=b'00 Horizontal Position ignore + // bit[77:74]=2 Square bit[78]=0 bit[86:79]=0 bit[94:87]='0 no group info' bit[95]=0 not a bay + 0x30, 0x08, 0x00, 0x00, + //127:96 -bit[96]=0 not Ejectable bit[97]=0 OSPM Ejection not required Bit[105:98]=0 no Cabinet Number + // bit[113:106]=0 no Card cage Number bit[114]=0 no reference shape Bit[118:115]=0 no rotation Bit[123:119]=0 no order + 0x00, 0x00, 0x00, 0x00, + //159:128 Vert. and Horiz. Offsets not supplied + 0xFF, 0xFF, 0xFF, 0xFF + } + }) + Return (PLDP) + } + } + } //end of root hub + +} // end of XHC1 + diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PciTree.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PciTree.asl new file mode 100644 index 0000000000..84a7ee21d0 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/PciTree.asl @@ -0,0 +1,373 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Sandy Bridge *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + +Scope(\_SB) +{ + +//RTC + Device(RTC) // RTC + { + Name(_HID,EISAID("PNP0B00")) + + Name(_CRS,ResourceTemplate() + { + IO(Decode16,0x70,0x70,0x01,0x08) + }) + } +//RTC + + Device(HPET) // High Performance Event Timer + { + Name (_HID, EisaId ("PNP0103")) + Name (_UID, 0x00) + Method (_STA, 0, NotSerialized) + { + Return (0x0F) + } + + Method (_CRS, 0, Serialized) + { + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, + 0xFED00000, // Address Base + 0x00000400, // Address Length + ) + Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, ) + { + 0x00000008, //0xB HPET-2 + } + }) + Return (RBUF) + } + } +//HPET + + Name(PR00, Package() + { +// SD Host #0 - eMMC + Package() {0x0010FFFF, 0, LNKA, 0 }, +// SD Host #1 - SDIO + Package() {0x0011FFFF, 0, LNKB, 0 }, +// SD Host #2 - SD Card + Package() {0x0012FFFF, 0, LNKC, 0 }, +// SATA Controller + Package() {0x0013FFFF, 0, LNKD, 0 }, +// xHCI Host + Package() {0x0014FFFF, 0, LNKE, 0 }, +// Low Power Audio Engine + Package() {0x0015FFFF, 0, LNKF, 0 }, +// USB OTG + Package() {0x0016FFFF, 0, LNKG, 0 }, +// MIPI-HSI/eMMC4.5 + Package() {0x0017FFFF, 0, LNKH, 0 }, +// LPSS2 DMA +// LPSS2 I2C #4 + Package() {0x0018FFFF, 0, LNKB, 0 }, +// LPSS2 I2C #1 +// LPSS2 I2C #5 + Package() {0x0018FFFF, 2, LNKD, 0 }, +// LPSS2 I2C #2 +// LPSS2 I2C #6 + Package() {0x0018FFFF, 3, LNKC, 0 }, +// LPSS2 I2C #3 +// LPSS2 I2C #7 + Package() {0x0018FFFF, 1, LNKA, 0 }, +// SeC + Package() {0x001AFFFF, 0, LNKF, 0 }, +// +// High Definition Audio Controller + Package() {0x001BFFFF, 0, LNKG, 0 }, +// +// EHCI Controller + Package() {0x001DFFFF, 0, LNKH, 0 }, +// LPSS DMA + Package() {0x001EFFFF, 0, LNKD, 0 }, +// LPSS I2C #0 + Package() {0x001EFFFF, 3, LNKA, 0 }, +// LPSS I2C #1 + Package() {0x001EFFFF, 1, LNKB, 0 }, +// LPSS PCM + Package() {0x001EFFFF, 2, LNKC, 0 }, +// LPSS I2S +// LPSS HS-UART #0 +// LPSS HS-UART #1 +// LPSS SPI +// LPC Bridge +// +// SMBus Controller + Package() {0x001FFFFF, 1, LNKC, 0 }, +// +// PCIE Root Port #1 + Package() {0x001CFFFF, 0, LNKA, 0 }, +// PCIE Root Port #2 + Package() {0x001CFFFF, 1, LNKB, 0 }, +// PCIE Root Port #3 + Package() {0x001CFFFF, 2, LNKC, 0 }, +// PCIE Root Port #4 + Package() {0x001CFFFF, 3, LNKD, 0 }, + +// Host Bridge +// Mobile IGFX + Package() {0x0002FFFF, 0, LNKA, 0 }, + }) + + Name(AR00, Package() + { +// SD Host #0 - eMMC + Package() {0x0010FFFF, 0, 0, 16 }, +// SD Host #1 - SDIO + Package() {0x0011FFFF, 0, 0, 17 }, +// SD Host #2 - SD Card + Package() {0x0012FFFF, 0, 0, 18 }, +// SATA Controller + Package() {0x0013FFFF, 0, 0, 19 }, +// xHCI Host + Package() {0x0014FFFF, 0, 0, 20 }, +// Low Power Audio Engine + Package() {0x0015FFFF, 0, 0, 21 }, +// USB OTG + Package() {0x0016FFFF, 0, 0, 22 }, +// +// MIPI-HSI + Package() {0x0017FFFF, 0, 0, 23 }, +// +// LPSS2 DMA +// LPSS2 I2C #4 + Package() {0x0018FFFF, 0, 0, 17 }, +// LPSS2 I2C #1 +// LPSS2 I2C #5 + Package() {0x0018FFFF, 2, 0, 19 }, +// LPSS2 I2C #2 +// LPSS2 I2C #6 + Package() {0x0018FFFF, 3, 0, 18 }, +// LPSS2 I2C #3 +// LPSS2 I2C #7 + Package() {0x0018FFFF, 1, 0, 16 }, + +// SeC + Package() {0x001AFFFF, 0, 0, 21 }, +// +// High Definition Audio Controller + Package() {0x001BFFFF, 0, 0, 22 }, +// +// EHCI Controller + Package() {0x001DFFFF, 0, 0, 23 }, +// LPSS DMA + Package() {0x001EFFFF, 0, 0, 19 }, +// LPSS I2C #0 + Package() {0x001EFFFF, 3, 0, 16 }, +// LPSS I2C #1 + Package() {0x001EFFFF, 1, 0, 17 }, +// LPSS PCM + Package() {0x001EFFFF, 2, 0, 18 }, +// LPSS I2S +// LPSS HS-UART #0 +// LPSS HS-UART #1 +// LPSS SPI +// LPC Bridge +// +// SMBus Controller + Package() {0x001FFFFF, 1, 0, 18 }, +// +// PCIE Root Port #1 + Package() {0x001CFFFF, 0, 0, 16 }, +// PCIE Root Port #2 + Package() {0x001CFFFF, 1, 0, 17 }, +// PCIE Root Port #3 + Package() {0x001CFFFF, 2, 0, 18 }, +// PCIE Root Port #4 + Package() {0x001CFFFF, 3, 0, 19 }, +// Host Bridge +// Mobile IGFX + Package() {0x0002FFFF, 0, 0, 16 }, + }) + + Name(PR04, Package() + { +// PCIE Port #1 Slot + Package() {0x0000FFFF, 0, LNKA, 0 }, + Package() {0x0000FFFF, 1, LNKB, 0 }, + Package() {0x0000FFFF, 2, LNKC, 0 }, + Package() {0x0000FFFF, 3, LNKD, 0 }, + }) + + Name(AR04, Package() + { +// PCIE Port #1 Slot + Package() {0x0000FFFF, 0, 0, 16 }, + Package() {0x0000FFFF, 1, 0, 17 }, + Package() {0x0000FFFF, 2, 0, 18 }, + Package() {0x0000FFFF, 3, 0, 19 }, + }) + + Name(PR05, Package() + { +// PCIE Port #2 Slot + Package() {0x0000FFFF, 0, LNKB, 0 }, + Package() {0x0000FFFF, 1, LNKC, 0 }, + Package() {0x0000FFFF, 2, LNKD, 0 }, + Package() {0x0000FFFF, 3, LNKA, 0 }, + }) + + Name(AR05, Package() + { +// PCIE Port #2 Slot + Package() {0x0000FFFF, 0, 0, 17 }, + Package() {0x0000FFFF, 1, 0, 18 }, + Package() {0x0000FFFF, 2, 0, 19 }, + Package() {0x0000FFFF, 3, 0, 16 }, + }) + + Name(PR06, Package() + { +// PCIE Port #3 Slot + Package() {0x0000FFFF, 0, LNKC, 0 }, + Package() {0x0000FFFF, 1, LNKD, 0 }, + Package() {0x0000FFFF, 2, LNKA, 0 }, + Package() {0x0000FFFF, 3, LNKB, 0 }, + }) + + Name(AR06, Package() + { +// PCIE Port #3 Slot + Package() {0x0000FFFF, 0, 0, 18 }, + Package() {0x0000FFFF, 1, 0, 19 }, + Package() {0x0000FFFF, 2, 0, 16 }, + Package() {0x0000FFFF, 3, 0, 17 }, + }) + + Name(PR07, Package() + { +// PCIE Port #4 Slot + Package() {0x0000FFFF, 0, LNKD, 0 }, + Package() {0x0000FFFF, 1, LNKA, 0 }, + Package() {0x0000FFFF, 2, LNKB, 0 }, + Package() {0x0000FFFF, 3, LNKC, 0 }, + }) + + Name(AR07, Package() + { +// PCIE Port #4 Slot + Package() {0x0000FFFF, 0, 0, 19 }, + Package() {0x0000FFFF, 1, 0, 16 }, + Package() {0x0000FFFF, 2, 0, 17 }, + Package() {0x0000FFFF, 3, 0, 18 }, + }) + + Name(PR01, Package() + { +// PCI slot 1 + Package() {0x0000FFFF, 0, LNKF, 0 }, + Package() {0x0000FFFF, 1, LNKG, 0 }, + Package() {0x0000FFFF, 2, LNKH, 0 }, + Package() {0x0000FFFF, 3, LNKE, 0 }, +// PCI slot 2 + Package() {0x0001FFFF, 0, LNKG, 0 }, + Package() {0x0001FFFF, 1, LNKF, 0 }, + Package() {0x0001FFFF, 2, LNKE, 0 }, + Package() {0x0001FFFF, 3, LNKH, 0 }, +// PCI slot 3 + Package() {0x0002FFFF, 0, LNKC, 0 }, + Package() {0x0002FFFF, 1, LNKD, 0 }, + Package() {0x0002FFFF, 2, LNKB, 0 }, + Package() {0x0002FFFF, 3, LNKA, 0 }, +// PCI slot 4 + Package() {0x0003FFFF, 0, LNKD, 0 }, + Package() {0x0003FFFF, 1, LNKC, 0 }, + Package() {0x0003FFFF, 2, LNKF, 0 }, + Package() {0x0003FFFF, 3, LNKG, 0 }, + }) + + Name(AR01, Package() + { +// PCI slot 1 + Package() {0x0000FFFF, 0, 0, 21 }, + Package() {0x0000FFFF, 1, 0, 22 }, + Package() {0x0000FFFF, 2, 0, 23 }, + Package() {0x0000FFFF, 3, 0, 20 }, +// PCI slot 2 + Package() {0x0001FFFF, 0, 0, 22 }, + Package() {0x0001FFFF, 1, 0, 21 }, + Package() {0x0001FFFF, 2, 0, 20 }, + Package() {0x0001FFFF, 3, 0, 23 }, +// PCI slot 3 + Package() {0x0002FFFF, 0, 0, 18 }, + Package() {0x0002FFFF, 1, 0, 19 }, + Package() {0x0002FFFF, 2, 0, 17 }, + Package() {0x0002FFFF, 3, 0, 16 }, +// PCI slot 4 + Package() {0x0003FFFF, 0, 0, 19 }, + Package() {0x0003FFFF, 1, 0, 18 }, + Package() {0x0003FFFF, 2, 0, 21 }, + Package() {0x0003FFFF, 3, 0, 22 }, + }) +//--------------------------------------------------------------------------- +// List of IRQ resource buffers compatible with _PRS return format. +//--------------------------------------------------------------------------- +// Naming legend: +// RSxy, PRSy - name of the IRQ resource buffer to be returned by _PRS, "xy" - last two characters of IRQ Link name. +// Note. PRSy name is generated if IRQ Link name starts from "LNK". +// HLxy , LLxy - reference names, can be used to access bit mask of available IRQs. HL and LL stand for active High(Low) Level triggered Irq model. +//--------------------------------------------------------------------------- + Name(PRSA, ResourceTemplate() // Link name: LNKA + { + IRQ(Level, ActiveLow, Shared, LLKA) {3,4,5,6,10,11,12,14,15} + }) + Alias(PRSA,PRSB) // Link name: LNKB + Alias(PRSA,PRSC) // Link name: LNKC + Alias(PRSA,PRSD) // Link name: LNKD + Alias(PRSA,PRSE) // Link name: LNKE + Alias(PRSA,PRSF) // Link name: LNKF + Alias(PRSA,PRSG) // Link name: LNKG + Alias(PRSA,PRSH) // Link name: LNKH +//--------------------------------------------------------------------------- +// Begin PCI tree object scope +//--------------------------------------------------------------------------- + + Device(PCI0) // PCI Bridge "Host Bridge" + { + Name(_HID, EISAID("PNP0A08")) // Indicates PCI Express/PCI-X Mode2 host hierarchy + Name(_CID, EISAID("PNP0A03")) // To support legacy OS that doesn't understand the new HID + Name(_ADR, 0x00000000) + Method(^BN00, 0) { return(0x0000) } // Returns default Bus number for Peer PCI busses. Name can be overriden with control method placed directly under Device scope + Method(_BBN, 0) { return(BN00()) } // Bus number, optional for the Root PCI Bus + Name(_UID, 0x0000) // Unique Bus ID, optional + Name(_DEP, Package(0x1) + { + PEPD + }) + + Method(_PRT,0) + { + If(PICM) {Return(AR00)} // APIC mode + Return (PR00) // PIC Mode + } // end _PRT + + include("HOST_BUS.ASL") + Device(LPCB) // LPC Bridge + { + Name(_ADR, 0x001F0000) + include("LpcB.asl") + } // end "LPC Bridge" + + } // end PCI0 Bridge "Host Bridge" +} // end _SB scope diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Platform.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Platform.asl new file mode 100644 index 0000000000..5f269be615 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Platform.asl @@ -0,0 +1,830 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + + +// Define the following External variables to prevent a WARNING when +// using ASL.EXE and an ERROR when using IASL.EXE. + +External(PDC0) +External(PDC1) +External(PDC2) +External(PDC3) +External(CFGD) +External(\_PR.CPU0._PPC, IntObj) +External(\_SB.PCI0.LPCB.TPM.PTS, MethodObj) +External(\_SB.STR3, DeviceObj) +External(\_SB.I2C1.BATC, DeviceObj) +External(\_SB.DPTF, DeviceObj) +External(\_SB.TCHG, DeviceObj) +External(\_SB.IAOE.PTSL) +External(\_SB.IAOE.WKRS) + +// +// Create a Global MUTEX. +// +Mutex(MUTX,0) + + + +// Port 80h Update: +// Update 8 bits of the 32-bit Port 80h. +// +// Arguments: +// Arg0: 0 = Write Port 80h, Bits 7:0 Only. +// 1 = Write Port 80h, Bits 15:8 Only. +// 2 = Write Port 80h, Bits 23:16 Only. +// 3 = Write Port 80h, Bits 31:24 Only. +// Arg1: 8-bit Value to write +// +// Return Value: +// None + +Method(P8XH,2,Serialized) +{ + If(LEqual(Arg0,0)) // Write Port 80h, Bits 7:0. + { + Store(Or(And(P80D,0xFFFFFF00),Arg1),P80D) + } + + If(LEqual(Arg0,1)) // Write Port 80h, Bits 15:8. + { + Store(Or(And(P80D,0xFFFF00FF),ShiftLeft(Arg1,8)),P80D) + } + + If(LEqual(Arg0,2)) // Write Port 80h, Bits 23:16. + { + Store(Or(And(P80D,0xFF00FFFF),ShiftLeft(Arg1,16)),P80D) + } + + If(LEqual(Arg0,3)) // Write Port 80h, Bits 31:24. + { + Store(Or(And(P80D,0x00FFFFFF),ShiftLeft(Arg1,24)),P80D) + } + +} + +// +// Define SW SMI port as an ACPI Operating Region to use for generate SW SMI. +// +OperationRegion (SPRT, SystemIO, 0xB2, 2) +Field (SPRT, ByteAcc, Lock, Preserve) +{ + SSMP, 8 +} + +// The _PIC Control Method is optional for ACPI design. It allows the +// OS to inform the ASL code which interrupt controller is being used, +// the 8259 or APIC. The reference code in this document will address +// PCI IRQ Routing and resource allocation for both cases. +// +// The values passed into _PIC are: +// 0 = 8259 +// 1 = IOAPIC + +Method(\_PIC,1) +{ + Store(Arg0,GPIC) + Store(Arg0,PICM) +} + +OperationRegion(SWC0, SystemIO, 0x610, 0x0F) +Field(SWC0, ByteAcc, NoLock, Preserve) +{ + G1S, 8, //SWC GPE1_STS + Offset(0x4), + G1E, 8, + Offset(0xA), + G1S2, 8, //SWC GPE1_STS_2 + G1S3, 8 //SWC GPE1_STS_3 +} + +OperationRegion (SWC1, SystemIO, \PMBS, 0x2C) +Field(SWC1, DWordAcc, NoLock, Preserve) +{ + Offset(0x20), + G0S, 32, //GPE0_STS + Offset(0x28), + G0EN, 32 //GPE0_EN +} + +// Prepare to Sleep. The hook is called when the OS is about to +// enter a sleep state. The argument passed is the numeric value of +// the Sx state. + +Method(_PTS,1) +{ + Store(0,P80D) // Zero out the entire Port 80h DWord. + P8XH(0,Arg0) // Output Sleep State to Port 80h, Byte 0. + + //clear the 3 SWC status bits + Store(Ones, G1S3) + Store(Ones, G1S2) + Store(1, G1S) + + //set SWC GPE1_EN + Store(1,G1E) + + //clear GPE0_STS + Store(Ones, G0S) + + + If(LEqual(Arg0,3)) // If S3 Suspend + { + // + // Disable Digital Thermal Sensor function when doing S3 suspend + // + If(CondRefOf(DTSE)) + { + If(LGreaterEqual(DTSE, 0x01)) + { + Store(30, DTSF) // DISABLE_UPDATE_DTS_EVERY_SMI + Store(0xD0, SSMP) // DTS SW SMI + } + } + } +} + +// Wake. This hook is called when the OS is about to wake from a +// sleep state. The argument passed is the numeric value of the +// sleep state the system is waking from. +Method(_WAK,1,Serialized) +{ + P8XH(1,0xAB) // Beginning of _WAK. + + Notify(\_SB.PWRB,0x02) + + If(NEXP) + { + // Reinitialize the Native PCI Express after resume + If(And(OSCC,0x02)) + { + \_SB.PCI0.NHPG() + } + + If(And(OSCC,0x04)) // PME control granted? + { + \_SB.PCI0.NPME() + } + } + + If(LOr(LEqual(Arg0,3), LEqual(Arg0,4))) // If S3 or S4 Resume + { + + + // If CMP is enabled, we may need to restore the C-State and/or + // P-State configuration, as it may have been saved before the + // configuration was finalized based on OS/driver support. + // + // CFGD[24] = Two or more cores enabled + // + If(And(CFGD,0x01000000)) + { + // + // If CMP and the OSYS is WinXP SP1, we will enable C1-SMI if + // C-States are enabled. + // + // CFGD[7:4] = C4, C3, C2, C1 Capable/Enabled + // + // + } + + // Windows XP SP2 does not properly restore the P-State + // upon resume from S4 or S3 with degrade modes enabled. + // Use the existing _PPC methods to cycle the available + // P-States such that the processor ends up running at + // the proper P-State. + // + // Note: For S4, another possible W/A is to always boot + // the system in LFM. + // + If(LEqual(OSYS,2002)) + { + If(And(CFGD,0x01)) + { + If(LGreater(\_PR.CPU0._PPC,0)) + { + Subtract(\_PR.CPU0._PPC,1,\_PR.CPU0._PPC) + PNOT() + Add(\_PR.CPU0._PPC,1,\_PR.CPU0._PPC) + PNOT() + } + Else + { + Add(\_PR.CPU0._PPC,1,\_PR.CPU0._PPC) + PNOT() + Subtract(\_PR.CPU0._PPC,1,\_PR.CPU0._PPC) + PNOT() + } + } + } + } + Return(Package() {0,0}) +} + +// Power Notification: +// Perform all needed OS notifications during a +// Power Switch. +// +// Arguments: +// None +// +// Return Value: +// None + +Method(PNOT,0,Serialized) +{ + // If MP enabled and driver support is present, notify all + // processors. + + If(MPEN) + { + If(And(PDC0,0x0008)) + { + Notify(\_PR.CPU0,0x80) // Eval CPU0 _PPC. + + If(And(PDC0,0x0010)) + { + Sleep(100) + Notify(\_PR.CPU0,0x81) // Eval _CST. + } + } + + If(And(PDC1,0x0008)) + { + Notify(\_PR.CPU1,0x80) // Eval CPU1 _PPC. + + If(And(PDC1,0x0010)) + { + Sleep(100) + Notify(\_PR.CPU1,0x81) // Eval _CST. + } + } + + If(And(PDC2,0x0008)) + { + Notify(\_PR.CPU2,0x80) // Eval CPU2 _PPC. + + If(And(PDC2,0x0010)) + { + Sleep(100) + Notify(\_PR.CPU2,0x81) // Eval _CST. + } + } + + If(And(PDC3,0x0008)) + { + Notify(\_PR.CPU3,0x80) // Eval CPU3 _PPC. + + If(And(PDC3,0x0010)) + { + Sleep(100) + Notify(\_PR.CPU3,0x81) // Eval _CST. + } + } + } + Else + { + Notify(\_PR.CPU0,0x80) // Eval _PPC. + Sleep(100) + Notify(\_PR.CPU0,0x81) // Eval _CST + } +} + +// +// System Bus +// +Scope(\_SB) +{ + Name(CRTT, 110) // Processor critical temperature + Name(ACTT, 77) // Active temperature limit for processor participant + Name(GCR0, 70) // Critical temperature for Generic participant 0 in degree celsius + Name(GCR1, 70) // Critical temperature for Generic participant 1 in degree celsius + Name(GCR2, 70) // Critical temperature for Generic participant 2 in degree celsius + Name(GCR3, 70) // Critical temperature for Generic participant 3 in degree celsius + Name(GCR4, 70) // Critical temperature for Generic participant 4 in degree celsius + Name(GCR5, 70) // Critical temperature for Generic participant 5 in degree celsius + Name(GCR6, 70) // Critical temperature for Generic participant 6 in degree celsius + Name(PST0, 60) // Passive temperature limit for Generic Participant 0 in degree celsius + Name(PST1, 60) // Passive temperature limit for Generic Participant 1 in degree celsius + Name(PST2, 60) // Passive temperature limit for Generic Participant 2 in degree celsius + Name(PST3, 60) // Passive temperature limit for Generic Participant 3 in degree celsius + Name(PST4, 60) // Passive temperature limit for Generic Participant 4 in degree celsius + Name(PST5, 60) // Passive temperature limit for Generic Participant 5 in degree celsius + Name(PST6, 60) // Passive temperature limit for Generic Participant 6 in degree celsius + Name(LPMV, 3) + Name(PDBG, 0) // DPTF Super debug option + Name(PDPM, 1) // DPTF DPPM enable + Name(PDBP, 1) // DPTF DBPT enable (dynamic battery protection technology) + Name(DLPO, Package() + { + 0x1, // Revision + 0x1, // LPO Enable + 0x1, // LPO StartPState + 25, // LPO StepSize + 0x1, // + 0x1, // + }) + Name(BRQD, 0x00) // This is used to determine if DPTF display participant requested Brightness level change + // or it is from Graphics driver. Value of 1 is for DPTF else it is 0 + + Method(_INI,0) + { + // NVS has stale DTS data. Get and update the values + // with current temperatures. Note that this will also + // re-arm any AP Thermal Interrupts. + // Read temperature settings from global NVS + Store(DPCT, CRTT) + Store(Subtract(DPPT, 8), ACTT) // Active Trip point = Passive trip point - 8 + Store(DGC0, GCR0) + Store(DGC0, GCR1) + Store(DGC1, GCR2) + Store(DGC1, GCR3) + Store(DGC1, GCR4) + Store(DGC2, GCR5) + Store(DGC2, GCR6) + Store(DGP0, PST0) + Store(DGP0, PST1) + Store(DGP1, PST2) + Store(DGP1, PST3) + Store(DGP1, PST4) + Store(DGP2, PST5) + Store(DGP2, PST6) + // Read Current low power mode setting from global NVS + Store(DLPM, LPMV) + + + // Update DPTF Super Debug option + Store(DDBG, PDBG) + + + // Update DPTF LPO Options + Store(LPOE, Index(DLPO,1)) + Store(LPPS, Index(DLPO,2)) + Store(LPST, Index(DLPO,3)) + Store(LPPC, Index(DLPO,4)) + Store(LPPF, Index(DLPO,5)) + Store(DPME, PDPM) + } + + // Define a (Control Method) Power Button. + Device(PWRB) + { + Name(_HID,EISAID("PNP0C0C")) + + // GPI_SUS0 = GPE16 = Waketime SCI. The PRW isn't working when + // placed in any of the logical locations ( PS2K, PS2M), + // so a Power Button Device was created specifically + // for the WAKETIME_SCI PRW. + + Name(_PRW, Package() {16,4}) + } + + Device(SLPB) + { + Name(_HID, EISAID("PNP0C0E")) + } // END SLPB + + Scope(PCI0) + { + Method(_INI,0) + { + // Determine the OS and store the value, where: + // + // OSYS = 2009 = Windows 7 and Windows Server 2008 R2. + // OSYS = 2012 = Windows 8 and Windows Server 2012. + // + // Assume Windows 7 at a minimum. + + Store(2009,OSYS) + + // Check for a specific OS which supports _OSI. + + If(CondRefOf(\_OSI,Local0)) + { + // Linux returns _OSI = TRUE for numerous Windows + // strings so that it is fully compatible with + // BIOSes available in the market today. There are + // currently 2 known exceptions to this model: + // 1) Video Repost - Linux supports S3 without + // requireing a Driver, meaning a Video + // Repost will be required. + // 2) On-Screen Branding - a full CMT Logo + // is limited to the WIN2K and WINXP + // Operating Systems only. + + // Use OSYS for Windows Compatibility. + If(\_OSI("Windows 2009")) // Windows 7 or Windows Server 2008 R2 + { + Store(2009,OSYS) + } + If(\_OSI("Windows 2012")) // Windows 8 or Windows Server 2012 + { + Store(2012,OSYS) + } + If(\_OSI("Windows 2013")) //Windows Blue + { + Store(2013,OSYS) + } + + // + // If CMP is enabled, enable SMM C-State + // coordination. SMM C-State coordination + // will be disabled in _PDC if driver support + // for independent C-States deeper than C1 + // is indicated. + } + } + + Method(NHPG,0,Serialized) + { + + } + + Method(NPME,0,Serialized) + { + + } + } // end Scope(PCI0) + + Device (GPED) //virtual GPIO device for ASL based AC/Battery/Expection notification + { + Name (_ADR, 0) + Name (_HID, "INT0002") + Name (_CID, "INT0002") + Name (_DDN, "Virtual GPIO controller" ) + Name (_UID, 1) + + Method (_CRS, 0x0, Serialized) + { + Name (RBUF, ResourceTemplate () + { + Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, ) {0x9} // Was 9 + }) + Return (RBUF) + } + + Method (_STA, 0x0, NotSerialized) + { + Return(0x0) + } + + Method (_AEI, 0x0, Serialized) + { + Name(RBUF, ResourceTemplate() + { + GpioInt(Edge, ActiveHigh, ExclusiveAndWake, PullDown,,"\\_SB.GPED",) {2} //pin 2 + }) + Return(RBUF) + } + + Method(_E02) // _Exx method will be called when interrupt is raised + { + If (LEqual (PWBS, 1)) + { + Store (1, PWBS) //Clear PowerButton Status + } + If (LEqual (PMEB, 1)) + { + Store (1, PMEB) //Clear PME_B0_STS + } + If (LEqual (\_SB.PCI0.SATA.PMES, 1)) + { + Store (1, \_SB.PCI0.SATA.PMES) + Notify (\_SB.PCI0.SATA, 0x02) + } + // + // eMMC 4.41 + // + If (LAnd(LEqual (\_SB.PCI0.EM41.PMES, 1), LEqual(PCIM, 1))) + { + Store (1, \_SB.PCI0.EM41.PMES) + Notify (\_SB.PCI0.EM41, 0x02) + } + + // + // eMMC 4.5 + // + If (LAnd(LEqual (\_SB.PCI0.EM45.PMES, 1), LEqual(PCIM, 1))) + { + Store (1, \_SB.PCI0.EM45.PMES) + Notify (\_SB.PCI0.EM45, 0x02) + } + + If (LEqual(HDAD, 0)) + { + If (LEqual (\_SB.PCI0.HDEF.PMES, 1)) + { + Store (1, \_SB.PCI0.HDEF.PMES) + Notify (\_SB.PCI0.HDEF, 0x02) + } + } + + If (LEqual (\_SB.PCI0.EHC1.PMES, 1)) + { + Store (1, \_SB.PCI0.EHC1.PMES) + Notify (\_SB.PCI0.EHC1, 0x02) + } + If (LEqual (\_SB.PCI0.XHC1.PMES, 1)) + { + Store (1, \_SB.PCI0.XHC1.PMES) + Notify (\_SB.PCI0.XHC1, 0x02) + } + If (LEqual (\_SB.PCI0.SEC0.PMES, 1)) + { + Or (\_SB.PCI0.SEC0.PMES, Zero, \_SB.PCI0.SEC0.PMES) + Notify (\_SB.PCI0.SEC0, 0x02) + } + } + } // Device (GPED) + + //-------------------- + // GPIO + //-------------------- + Device (GPO0) + { + Name (_ADR, 0) + Name (_HID, "INT33FC") + Name (_CID, "INT33B2") + Name (_DDN, "ValleyView2 General Purpose Input/Output (GPIO) controller" ) + Name (_UID, 1) + Method (_CRS, 0x0, Serialized) + { + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x0FED0C000, 0x00001000) + Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , ) {49} + + }) + Return (RBUF) + } + + Method (_STA, 0x0, NotSerialized) + { + // + // GPO driver will report present if any of below New IO bus exist + // + If (LOr(LEqual(L11D, 0), LEqual(L12D, 0))) // LPIO1 PWM #1 or #2 exist + { Return(0xF) } + If (LOr(LEqual(L13D, 0), LEqual(L14D, 0))) // LPIO1 HS-UART #1 or #2 exist + { Return(0xF) } + If (LOr(LEqual(L15D, 0), LEqual(SD1D, 0))) // LPIO1 SPI or SCC SDIO #1 exist + { Return(0xF) } + If (LOr(LEqual(SD2D, 0), LEqual(SD3D, 0))) // SCC SDIO #2 or #3 exist + { Return(0xF) } + If (LOr(LEqual(L21D, 0), LEqual(L22D, 0))) // LPIO2 I2C #1 or #2 exist + { Return(0xF) } + If (LOr(LEqual(L23D, 0), LEqual(L24D, 0))) // LPIO2 I2C #3 or #4 exist + { Return(0xF) } + If (LOr(LEqual(L25D, 0), LEqual(L26D, 0))) // LPIO2 I2C #5 or #6 exist + { Return(0xF) } + If (LEqual(L27D, 0)) // LPIO2 I2C #7 exist + { Return(0xF) } + + Return(0x0) + } + + // Track status of GPIO OpRegion availability for this controller + Name(AVBL, 0) + Method(_REG,2) + { + If (Lequal(Arg0, 8)) + { + Store(Arg1, ^AVBL) + } + } + + OperationRegion(GPOP, SystemIo, \GPBS, 0x50) + Field(GPOP, ByteAcc, NoLock, Preserve) { + Offset(0x28), // cfio_ioreg_SC_GP_LVL_63_32_ - [GPIO_BASE_ADDRESS] + 28h + , 21, + BTD3, 1, //This field is not used. Pin not defined in schematics. Closest is GPIO_S5_35 - COMBO_BT_WAKEUP + Offset(0x48), // cfio_ioreg_SC_GP_LVL_95_64_ - [GPIO_BASE_ADDRESS] + 48h + , 30, + SHD3, 1 //GPIO_S0_SC_95 - SENS_HUB_RST_N + } + + + + } // Device (GPO0) + + Device (GPO1) + { + Name (_ADR, 0) + Name (_HID, "INT33FC") + Name (_CID, "INT33B2") + Name (_DDN, "ValleyView2 GPNCORE controller" ) + Name (_UID, 2) + Method (_CRS, 0x0, Serialized) + { + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x0FED0D000, 0x00001000) + Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , ) {48} + }) + Return (RBUF) + } + + Method (_STA, 0x0, NotSerialized) + { + Return(\_SB.GPO0._STA) + } + } // Device (GPO1) + + Device (GPO2) + { + Name (_ADR, 0) + Name (_HID, "INT33FC") + Name (_CID, "INT33B2") + Name (_DDN, "ValleyView2 GPSUS controller" ) + Name (_UID, 3) + Method (_CRS, 0x0, Serialized) + { + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x0FED0E000, 0x00001000) + Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , ) {50} + }) + Return (RBUF) + } + + Method (_STA, 0x0, NotSerialized) + { + Return(^^GPO0._STA) + } + + // Track status of GPIO OpRegion availability for this controller + Name(AVBL, 0) + Method(_REG,2) + { + If (Lequal(Arg0, 8)) + { + Store(Arg1, ^AVBL) + } + } + //Manipulate GPIO line using GPIO operation regions. + Name (GMOD, ResourceTemplate () //One method of creating a Connection for OpRegion accesses in Field definitions + { + //is creating a named object that refers to the connection attributes + GpioIo (Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly, "\\_SB.GPO2") {21} //sus 21+128 BT+WLAN_ENABLE + }) + + OperationRegion(GPOP, SystemIo, \GPBS, 0x100) + Field(GPOP, ByteAcc, NoLock, Preserve) { + Offset(0x88), // cfio_ioreg_SUS_GP_LVL_31_0_ - [GPIO_BASE_ADDRESS] + 88h + , 20, + WFD3, 1 + } + + + } // Device (GPO2) + include ("PchScc.asl") + include ("PchLpss.asl") + + Scope(I2C7) + { + + } //End Scope(I2C7) + + // + // Device for Message Bus Interface + // + Device(MBID) + { + Name(_HID, "INT33BD") + Name(_CID, "INT33BD") + Name(_HRV, 2)//different from CLT's + Name(_UID, 1) + + Method (_CRS, 0, Serialized) + { + Name (RBUF, ResourceTemplate () + { + Memory32Fixed ( + ReadWrite, + 0xE00000D0, // Address Base + 0xC, // Address Length (MCR/MDR/MCRX) + ) + }) + Return (RBUF) + } + + + // + // custom opregion for MBI access + // + OperationRegion (REGS, 0x87, 0x0, 0x30) + Field (REGS, DWordAcc, NoLock, Preserve) + { + PORT, 32, // Message Port + REG, 32, // Message Target Register Address + DATA, 32, // Message Data + MASK, 32, // Mask bits for modify operation + BE, 32, // Message Write Byte enables: 0 - BYTE; 1 - WORD; 2 - DWORD + OP, 32 // Operations: 0 - read; 1 - write; 2 - modify + } + + // + // availability of the custom opregion + // + Name (AVBL, 0) + Method(_REG,2) + { + If (Lequal(Arg0, 0x87)) + { + Store(Arg1, ^AVBL) + } + } + + // + // Method Name: READ + // Arguments: + // Arg0: PORT + // Arg1: REG + // Arg2: BE + // Return Value: + // DATA + // + Method(READ, 3, Serialized) + { + Store(0xFFFFFFFF , Local0) + If (Lequal (AVBL, 1)) + { + Store(0, OP) // must be set at first, do not change! + Store(Arg0, PORT) + Store(Arg1, REG) + Store(Arg2, BE) + Store(DATA, Local0) + } + return(Local0) + } + + // + // Method Name: WRIT + // Arguments: + // Arg0: PORT + // Arg1: REG + // Arg2: BE + // Arg3: DATA + // Return Value: + // NONE + // + Method(WRIT, 4, Serialized) + { + If (Lequal (AVBL, 1)) + { + Store(1, OP) // must be set at first, do not change! + Store(Arg0, PORT) + Store(Arg1, REG) + Store(Arg2, BE) + Store(Arg3, DATA) + } + } + + // + // Method Name: MODI + // Arguments: + // Arg0: PORT + // Arg1: REG + // Arg2: BE + // Arg3: DATA + // Arg4: MASK + // Return Value: + // NONE + // + Method(MODI, 5, Serialized) + { + If (Lequal (AVBL, 1)) + { + Store(2, OP) // must be set at first, do not change! + Store(Arg0, PORT) + Store(Arg1, REG) + Store(Arg2, BE) + Store(Arg3, DATA) + Store(Arg4, MASK) + } + } + } + + +} // end Scope(\_SB) + +Name(PICM, 0) // Global Name, returns current Interrupt controller mode; updated from _PIC control method + diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/RTD3.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/RTD3.asl new file mode 100644 index 0000000000..eb607c6b2e --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/RTD3.asl @@ -0,0 +1,203 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ +DefinitionBlock ( + "Rtd3.aml", + "SSDT", + 1, + "AcpiRef", + "Msg_Rtd3", + 0x1000 +) +{ + External(RTD3) //flag if RTD3 is enabled + + If(LEqual(RTD3,1)) + { + Scope (\_SB) + { + Name(OSCI, 0) // \_SB._OSC DWORD2 input + Name(OSCO, 0) // \_SB._OSC DWORD2 output + + //Arg0 -- A buffer containing UUID + //Arg1 -- An Interger containing a Revision ID of the buffer format + //Arg2 -- An interger containing a count of entries in Arg3 + //Arg3 -- A buffer containing a list of DWORD capacities + Method(_OSC, 4, NotSerialized) + { + // Check for proper UUID + If(LEqual(Arg0, ToUUID("0811B06E-4A27-44F9-8D60-3CBBC22E7B48"))) + { + CreateDWordField(Arg3,0,CDW1) //bit1,2 is always clear + CreateDWordField(Arg3,4,CDW2) //Table 6-147 from ACPI spec + + Store(CDW2, OSCI) // Save DWord2 + Or(OSCI, 0x4, OSCO) // Only allow _PR3 support + + If(LNotEqual(Arg1,One)) + { + Or(CDW1,0x08,CDW1) // Unknown revision + } + + If(LNotEqual(OSCI, OSCO)) + { + Or(CDW1,0x10,CDW1) // Capabilities bits were masked + } + + Store(OSCO, CDW2) // Replace DWord2 + Return(Arg3) + } Else + { + Or(CDW1,4,CDW1) // Unrecognized UUID + Return(Arg3) + } + }// End _OSC + } + }//end of RTD3 condition + + + //USB RTD3 code + If(LEqual(RTD3,1)) + { + Scope(\_SB.PCI0.EHC1.HUBN.PR01.PR13) + { + Name(_PR0, Package() {\PR34}) + Name(_PR3, Package() {\PR34}) + + Method(_S0W, 0) + { + If(And(\_SB.OSCO, 0x04)) // PMEs can be genrated from D3cold + { + Return(4) // OS comprehends D3cold, as described via \_SB._OSC + } Else + { + Return(3) + } + } // End _S0W + } + + Scope(\_SB.PCI0.EHC1.HUBN.PR01.PR14) + { + Name(_PR0, Package() {\PR34}) + Name(_PR3, Package() {\PR34}) + + Method(_S0W, 0) + { + If(And(\_SB.OSCO, 0x04)) + { + Return(4) + } Else + { + Return(3) + } + } // End _S0W + } + + + Scope(\_SB.PCI0.EHC1.HUBN.PR01.PR15) + { + Name(_PR0, Package() {\PR56}) + Name(_PR3, Package() {\PR56}) + + Method(_S0W, 0) + { + If(And(\_SB.OSCO, 0x04)) + { + Return(4) + } Else + { + Return(3) + } + } // End _S0W + } + + Scope(\_SB.PCI0.EHC1.HUBN.PR01.PR16) + { + Name(_PR0, Package() {\PR56}) + Name(_PR3, Package() {\PR56}) + + Method(_S0W, 0) + { + If(And(\_SB.OSCO, 0x04)) + { + Return(4) + } Else + { + Return(3) + } + } // End _S0W + } + + Scope(\_SB.PCI0.XHC1) // XHCI host only controller + { + + Method(_PS0,0,Serialized) // set device into D0 state + { + } + + Method(_PS3,0,Serialized) // place device into D3H state + { + //write to PMCSR + } + + Method(_DSW, 3,Serialized) // enable or disable the device’s ability to wake a sleeping system. + { + } + } + + Scope(\_SB.PCI0.XHC1.RHUB.HS01) + { + + } + + Scope(\_SB.PCI0.XHC1.RHUB.SSP1) + { + + } + + Scope(\_SB.PCI0.XHC2) // OTG + { + + Method(_PS0,0,Serialized) // set device into D0 state + { + } + + Method(_PS3,0,Serialized) // place device into D3H state + { + //write to PMCSR + } + + Method(_DSW, 3,Serialized) // enable or disable the device’s ability to wake a sleeping system. + { + } + } + + Scope(\_SB.PCI0.XHC2.RHUB.HS01) + { + + } + + Scope(\_SB.PCI0.XHC2.RHUB.SSP1) + { + + } + } //If(LEqual(RTD3,1)) USB + +}//end of SSDT diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/THERMAL.ASL b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/THERMAL.ASL new file mode 100644 index 0000000000..e63f5bc69d --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/THERMAL.ASL @@ -0,0 +1,138 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + + +// THERMAL.ASL represents a Thermal Zone to be used for testing on the +// Customer Reference Boards. + +External(\_SB.DPTF.CTOK, MethodObj) + +Scope(\_TZ) +{ + + // Thermal Zone 1 = DTS Thermal Zone. + + ThermalZone(TZ01) + { + // Return the temperature at which the OS must perform a Critcal + // Shutdown. + + Method(_CRT,0,Serialized) + { + Return(Add(2732,Multiply(CRTT,10))) + } + + // Notifies ASL Code the current cooling mode. + // 0 - Active cooling + // 1 - Passive cooling + + Method(_SCP,1,Serialized) + { + Store(Arg0,CTYP) + } + + // _TMP (Temperature) + // + // Return the highest of the CPU temperatures to the OS. + // + // Arguments: (0) + // None + // Return Value: + // An Integer containing the current temperature of the thermal zone (in tenths of degrees Kelvin) + // + Method(_TMP,0,Serialized) + { + If(DTSE) + { + If(LGreater(DTS2, DTS1)) + { + Store(DTS2,Local0) + } else + { + Store(DTS1,Local0) + } + Return(Add(2732,Multiply(Local0,10))) + // + // Else return a static value if both EC and DTS are unavailable. + // + } Else + { + Return(3000) // (3000-2732)/10 = 26.8 degree C + } + } + + // Return the Processor(s) used for Passive Cooling. + + Method(_PSL,0,Serialized) + { + If(LEqual(MPEN, 4)) + { + // CMP - Throttling controls all four logical CPUs. + Return(Package() {\_PR.CPU0,\_PR.CPU1,\_PR.CPU2,\_PR.CPU3}) + } + + If(MPEN) + { + // CMP - Throttling controls both CPUs. + + Return(Package() {\_PR.CPU0,\_PR.CPU1}) + } + + Return(Package() {\_PR.CPU0}) + } + + // Returns the temperature at which the OS initiates CPU throttling. + + Method(_PSV,0,Serialized) + { + Return(Add(2732,Multiply(PSVT,10))) + } + + // Returns TC1 value used in the passive cooling formula. + + Method(_TC1,0,Serialized) + { + Return(TC1V) + } + + // Returns TC2 value used in the passive cooling formula. + + Method(_TC2,0,Serialized) + { + Return(TC2V) + } + + // Returns the sampling period used in the passive cooling formula. + + Method(_TSP,0,Serialized) + { + Return(TSPV) + } + + // Returns Hot Temperature + + Method(_HOT,0,Serialized) + { + Subtract(CRTT, 5, Local0) + Return(Add(2732,Multiply(Local0,10))) + } + } +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/UsbSbd.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/UsbSbd.asl new file mode 100644 index 0000000000..020bc97131 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/UsbSbd.asl @@ -0,0 +1,99 @@ +/************************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* MPG-MSAE *; +;* *; +;* Copyright (c) 1999 - 2014, Intel Corporation. *; +;* *; +;* This program and the accompanying materials are licensed and made available under*; +;* the terms and conditions of the BSD License that accompanies this distribution. *; +;* The full text of the license may be found at *; +;* http://opensource.org/licenses/bsd-license.php. *; +;* *; +;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, *; +;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. *; +;* *; +;* *; +;* This program has been developed by Intel Corporation. *; +;* Licensee has Intel's permission to incorporate this source code *; +;* into their product, royalty free. This source code may NOT be *; +;* redistributed to anyone without Intel's written permission. *; +;* *; +;* Intel specifically disclaims all warranties, express or *; +;* implied, and all liability, including consequential and other *; +;* indirect damages, for the use of this code, including liability *; +;* for infringement of any proprietary rights, and including the *; +;* warranties of merchantability and fitness for a particular *; +;* purpose. Intel does not assume any responsibility for any *; +;* errors which may appear in this code nor any responsibility to *; +;* update it. *; +;* *; +;* Version: See README.TXT *; +;* *; +;************************************************************************************/ + +// +// _DSM : Device Specific Method supporting USB Sideband Deferring function +// +// Arg0: UUID Unique function identifier +// Arg1: Integer Revision Level +// Arg2: Integer Function Index +// Arg3: Package Parameters +// +Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) +{ + + If (LEqual(Arg0, ToUUID ("A5FC708F-8775-4BA6-BD0C-BA90A1EC72F8"))) + { + // + // Switch by function index + // + Switch (ToInteger(Arg2)) + { + // + // Standard query - A bitmask of functions supported + // Supports function 0-2 + // + Case (0) + { + if (LEqual(Arg1, 1)) // test Arg1 for the revision + { + Return (Buffer () {0x07}) + } + else + { + Return (Buffer () {0}) + } + } + // + // USB Sideband Deferring Support + // 0: USB Sideband Deferring not supported on this device + // 1: USB Sideband Deferring supported + // + Case (1) + { + if (LEqual(SDGV,0xFF)) // check for valid GPE vector + { + Return (0) + } + else + { + Return (1) + } + } + // + // GPE Vector + // Return the bit offset within the GPE block of the GPIO (HOST_ALERT) driven by this device + // + Case (2) + { + Return (SDGV) + } + } + } + + Return (0) +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Video.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Video.asl new file mode 100644 index 0000000000..46d0aba7a9 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Video.asl @@ -0,0 +1,40 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Baytrail *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + + + + +// Brightness Notification: +// Generate a brightness related notification +// to the LFP if its populated. +// +// Arguments: +// Arg0: Notification value. +// +// Return Value: +// None +Method(BRTN,1,Serialized) +{ + If(LEqual(And(DIDX,0x0F00),0x400)) + { + Notify(\_SB.PCI0.GFX0.DD1F,Arg0) + } +} diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Vlv.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Vlv.asl new file mode 100644 index 0000000000..66c741f9c4 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/Vlv.asl @@ -0,0 +1,45 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + VLV.ASL + +Abstract: + + Baytrail PCI configuration space definition. + +--*/ +Scope (\_SB.PCI0) +{ + + Device(GFX0) // Mobile I.G.D + { + Name(_ADR, 0x00020000) + + Method(GDEP, 0) + { + If(LEqual(OSYS,2013)) + { + Name(_DEP, Package(0x1) + { + PEPD + }) + } + } + + include("INTELGFX.ASL") + include("INTELISPDev2.ASL") + } // end "Mobile I.G.D" +}//end scope diff --git a/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/token.asl b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/token.asl new file mode 100644 index 0000000000..8df5b315d5 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/AcpiTablesPCAT/token.asl @@ -0,0 +1,45 @@ +/**************************************************************************; +;* *; +;* *; +;* Intel Corporation - ACPI Reference Code for the Sandy Bridge *; +;* Family of Customer Reference Boards. *; +;* *; +;* *; +;* Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved *; +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;* *; +;* *; +;**************************************************************************/ + +Name(PMBS, 0x400) // ASL alias for ACPI I/O base address. +Name(SMIP, 0xb2) // I/O port to trigger SMI +Name(GPBS, 0x500) // GPIO Register Block address +Name(APCB, 0xfec00000) // Default I/O APIC(s) memory start address, 0x0FEC00000 - default, 0 - I/O APIC's disabled +Name(APCL, 0x1000) // I/O APIC(s) memory decoded range, 0x1000 - default, 0 - I/O APIC's not decoded +Name(PFDR, 0xfed03034) // PMC Function Disable Register +Name(PMCB, 0xfed03000) // PMC Base Address +Name(PCLK, 0xfed03060) // PMC Clock Control Register +Name(PUNB, 0xfed05000) // PUNIT Base Address +Name(IBAS, 0xfed08000) // ILB Base Address +Name(SRCB, 0xfed1c000) // RCBA (Root Complex Base Address) +Name(SRCL, 0x1000) // RCBA length +Name(HPTB, 0xfed00000) // Same as HPET_BASE_ADDRESS for ASL use +Name(PEBS, 0xe0000000) // PCIe Base +Name(PELN, 0x10000000) // +Name(FMBL, 0x1) // Platform Flavor - Mobile flavor for ASL code. +Name(FDTP, 0x2) // Platform Flavor - Desktop flavor for ASL code. +Name(SDGV, 0x1c) // UHCI Controller HOST_ALERT's bit offset within the GPE block. GPIO[0:15] corresponding to GPE[16:31] +Name(PEHP, 0x1) // _OSC: Pci Express Native Hot Plug Control +Name(SHPC, 0x0) // _OSC: Standard Hot Plug Controller (SHPC) Native Hot Plug control +Name(PEPM, 0x1) // _OSC: Pci Express Native Power Management Events control +Name(PEER, 0x1) // _OSC: Pci Express Advanced Error Reporting control +Name(PECS, 0x1) // _OSC: Pci Express Capability Structure control + diff --git a/Vlv2DeviceRefCodePkg/Include/Guid/Vlv2DeviceRefCodePkgTokenSpace.h b/Vlv2DeviceRefCodePkg/Include/Guid/Vlv2DeviceRefCodePkgTokenSpace.h new file mode 100644 index 0000000000..24faf23c1e --- /dev/null +++ b/Vlv2DeviceRefCodePkg/Include/Guid/Vlv2DeviceRefCodePkgTokenSpace.h @@ -0,0 +1,30 @@ +/*++ + +Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + Vlv2DeviceRefCodeTokenSpace.h + +Abstract: + + Interface definition details for GUID. + +--*/ +#ifndef __VLV2_REF_CODE__PKG_TOKEN_SPACE_GUID_H__ +#define __VLV2_REF_CODE__PKG_TOKEN_SPACE_GUID_H__ + +#define EFI_VLV_TOKEN_SPACE_GUID \ + { 0xca452c68, 0xdf0c, 0x45c9, {0x82, 0xfb, 0xea, 0xe4, 0x2b, 0x31, 0x29, 0x46}} +extern EFI_GUID gEfiVLVTokenSpaceGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Guid/PowerManagementAcpiTableStorage.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Guid/PowerManagementAcpiTableStorage.h new file mode 100644 index 0000000000..535258f774 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Guid/PowerManagementAcpiTableStorage.h @@ -0,0 +1,33 @@ + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + PowerManagementAcpiTableStorage.h + +Abstract: + + GUID definition for the Power Management ACPI table storage file name + +--*/ + +#ifndef _POWER_MANAGEMENT_ACPI_TABLE_STORAGE_H_ +#define _POWER_MANAGEMENT_ACPI_TABLE_STORAGE_H_ + +#define POWER_MANAGEMENT_ACPI_TABLE_STORAGE_GUID \ + { 0x161be597, 0xe9c5, 0x49db, 0xae, 0x50, 0xc4, 0x62, 0xab, 0x54, 0xee, 0xda } + +extern EFI_GUID gPowerManagementAcpiTableStorageGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Ppi/VlvPolicy.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Ppi/VlvPolicy.h new file mode 100644 index 0000000000..7b0c4193e6 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Ppi/VlvPolicy.h @@ -0,0 +1,110 @@ + +/*++ + +Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + VlvPolicy.h + +Abstract: + + Interface definition details between ValleyView MRC and platform drivers during PEI phase. + +--*/ + +#ifndef _VLV_POLICY_PPI_H_ +#define _VLV_POLICY_PPI_H_ + +// +// MRC Policy provided by platform for PEI phase {7D84B2C2-22A1-4372-B12C-EBB232D3A6A3} +// +#define VLV_POLICY_PPI_GUID \ + { \ + 0x7D84B2C2, 0x22A1, 0x4372, 0xB1, 0x2C, 0xEB, 0xB2, 0x32, 0xD3, 0xA6, 0xA3 \ + } + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gVlvPolicyPpiGuid; + +// +// PPI revision number +// Any backwards compatible changes to this PPI will result in an update in the revision number +// Major changes will require publication of a new PPI +// +#define MRC_PLATFORM_POLICY_PPI_REVISION 1 + +#ifndef MAX_SOCKETS +#define MAX_SOCKETS 4 +#endif + +#define S3_TIMING_DATA_LEN 9 +#define S3_READ_TRAINING_DATA_LEN 16 +#define S3_WRITE_TRAINING_DATA_LEN 12 + +#ifndef S3_RESTORE_DATA_LEN +#define S3_RESTORE_DATA_LEN (S3_TIMING_DATA_LEN + S3_READ_TRAINING_DATA_LEN + S3_WRITE_TRAINING_DATA_LEN) +#endif // S3_RESTORE_DATA_LEN +#pragma pack(1) +// +// MRC Platform Data Structure +// +typedef struct { + UINT8 SpdAddressTable[MAX_SOCKETS]; + UINT8 TSonDimmSmbusAddress[MAX_SOCKETS]; + + UINT16 SmbusBar; + UINT32 IchRcba; + UINT32 WdbBaseAddress; // Write Data Buffer area (WC caching mode) + UINT32 WdbRegionSize; + UINT32 SmBusAddress; + UINT8 UserBd; + UINT8 PlatformType; + UINT8 FastBoot; + UINT8 DynSR; +} VLV_PLATFORM_DATA; + + +typedef struct { + UINT16 MmioSize; + UINT16 GttSize; + UINT8 IgdDvmt50PreAlloc; + UINT8 PrimaryDisplay; + UINT8 PAVPMode; + UINT8 ApertureSize; +} GT_CONFIGURATION; + +typedef struct { + UINT8 EccSupport; + UINT16 DdrFreqLimit; + UINT8 MaxTolud; +} MEMORY_CONFIGURATION; + + +// +// MRC Platform Policiy PPI +// +typedef struct _VLV_POLICY_PPI { + UINT8 Revision; + VLV_PLATFORM_DATA PlatformData; + GT_CONFIGURATION GtConfig; + MEMORY_CONFIGURATION MemConfig; + VOID *S3DataPtr; // was called MRC_PARAMS_SAVE_RESTORE + UINT8 ISPEn; //ISP (IUNIT) Device Enabled + UINT8 ISPPciDevConfig; //ISP (IUNIT) Device Config: 0->B0/D2/F0 for Window OS, 1->B0D3/F0 for Linux OS +} VLV_POLICY_PPI; + +#pragma pack() + +#endif // _VLV_POLICY_PPI_H_ diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Protocol/PpmPlatformPolicy.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Protocol/PpmPlatformPolicy.h new file mode 100644 index 0000000000..4b9f9921a0 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Protocol/PpmPlatformPolicy.h @@ -0,0 +1,138 @@ +/** + Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/*++ + +Module Name: + + PpmPlatformPolicy.h + +Abstract: + + Interface definition details between PPM and platform drivers during DXE phase. + +--*/ +#ifndef _PPM_PLATFORM_POLICY_H_ +#define _PPM_PLATFORM_POLICY_H_ + +// +// PPM policy provided by platform for DXE phase {DDABFEAC-EF63-452c-8F39-ED7FAED8265E} +// +#define PPM_PLATFORM_POLICY_PROTOCOL_GUID \ + {0xddabfeac, 0xef63, 0x452c, 0x8f, 0x39, 0xed, 0x7f, 0xae, 0xd8, 0x26, 0x5e} + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gPpmPlatformPolicyProtocolGuid; + +// +// Forward reference for ANSI C compatibility +// +typedef struct _PPM_PLATFORM_POLICY_PROTOCOL PPM_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 +// Revision 2: Added T-states field to the PPM_FUNCTION_ENABLES structure, Renamed unused fields - CxPopUpEnable, CxPopDownEnable, FastC4ExitEnable +// Revision 3: Extended VidCpuid to 32 bits for extended CPUID support (Penryn) +// Revision 4: Added support for extended C6 residency enabling +// +#define PPM_PLATFORM_POLICY_PROTOCOL_REVISION 1 +#define PPM_PLATFORM_POLICY_PROTOCOL_REVISION_2 2 +#define PPM_PLATFORM_POLICY_PROTOCOL_REVISION_3 3 +#define PPM_PLATFORM_POLICY_PROTOCOL_REVISION_4 4 + +// +// Define maximum number of custom VID states supported +// +#ifndef MAX_CUSTOM_VID_TABLE_STATES +#define MAX_CUSTOM_VID_TABLE_STATES 6 +#endif +// +// Custom VID table +// +typedef struct { + UINT8 VidNumber; + UINT32 VidCpuid; + UINT16 VidMaxRatio; + UINT16 VidMaxVid; + UINT16 StateRatio[MAX_CUSTOM_VID_TABLE_STATES]; + UINT16 StateVid[MAX_CUSTOM_VID_TABLE_STATES]; +} PPM_CUSTOM_VID_TABLE; + +// +// PPM functional enables +// +typedef struct { + UINT8 EnableGv :1; // 0: Disabled; 1: Enabled + UINT8 EnableCx :1; + UINT8 EnableCxe :1; + UINT8 EnableC4 :1; + UINT8 EnableC6 :1; + UINT8 EnableC7 :1; + UINT8 EnableTm :1; + UINT8 Reserve00 :1; + UINT8 Reserve01 :1; + UINT8 EnableTurboMode :1; + UINT8 PowerLimit2 :1; + UINT8 EnableProcHot :1; + UINT8 Reserve02 :1; + UINT8 EnableCMP :1; + UINT8 TStatesEnable :1; + UINT8 Reserve03 :1; + UINT8 Reserve04 ; + +} PPM_FUNCTION_ENABLES; + + +// +// PPM Turbo settings +// +typedef struct _PPM_TURBO_SETTINGS { + UINT16 PowerLimit1; + UINT32 PowerLimit1Time; + UINT16 PowerLimit2; + UINT8 TurboPowerLimitLock; +} PPM_TURBO_SETTINGS; + +// +// Platform Policy +// +typedef struct _PPM_PLATFORM_POLICY_PROTOCOL { + UINT8 Revision; + PPM_FUNCTION_ENABLES FunctionEnables; + PPM_CUSTOM_VID_TABLE CustomVidTable; + PPM_TURBO_SETTINGS TurboSettings; + + UINT8 Reserve00; + UINT8 Reserve01; + UINT8 Reserve02; + UINT8 Reserve03; + UINT8 Reserve04; + UINT8 Reserve05; + UINT8 Reserve06; + + UINT8 S3RestoreMsrSwSmiNumber; + UINT8 Reserve07; + UINT32 Reserve08; + UINT8 Reserve09; + // + // Primary and Secondary Plane Current Limits + // + UINT16 Reserve10; + UINT8 Reserve11; +} PPM_PLATFORM_POLICY_PROTOCOL; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Types.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Types.h new file mode 100644 index 0000000000..c8085014e1 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Include/Types.h @@ -0,0 +1,61 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Types.h + +Abstract: + + This file include all the external data types. + +--*/ + +#ifndef _TYPES_H_ +#define _TYPES_H_ + + + +// +// Modifiers to abstract standard types to aid in debug of problems +// +#define CONST const +#define STATIC static +#define VOID void +#define VOLATILE volatile + +// +// Constants. They may exist in other build structures, so #ifndef them. +// +#ifndef TRUE +#define TRUE ((BOOLEAN) 1 == 1) +#endif + +#ifndef FALSE +#define FALSE ((BOOLEAN) 0 == 1) +#endif + +#ifndef NULL +#define NULL ((VOID *) 0) +#endif + +typedef UINT32 STATUS; +#define SUCCESS 0 +#define FAILURE 0xFFFFFFFF + +#ifndef MRC_DEADLOOP +#define MRC_DEADLOOP() while (TRUE) +#endif + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/PowerManagementAcpiTables.inf b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/PowerManagementAcpiTables.inf new file mode 100644 index 0000000000..72ed9c3199 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/PowerManagementAcpiTables.inf @@ -0,0 +1,45 @@ +# +#/*++ +# +#Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#Module Name: +# +# PowerManagementAcpiTables.inf +# +#Abstract: +# +# Component description file for the ACPI tables +# +#--*/ + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = PowerManagementAcpiTables2 + FILE_GUID = 161BE597-E9C5-49DB-AE50-C462AB54EEDA + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + +[sources.common] + Ssdt/Cpu0Cst.asl + Ssdt/Cpu0Ist.asl + Ssdt/Cpu0Tst.asl + Ssdt/ApCst.asl + Ssdt/ApIst.asl + Ssdt/ApTst.asl + Ssdt/CpuPm.asl + +[Packages] + MdePkg/MdePkg.dec diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/ApCst.asl b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/ApCst.asl new file mode 100644 index 0000000000..185750ee24 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/ApCst.asl @@ -0,0 +1,116 @@ +/*----------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + + Intel Silvermont Processor Power Management BIOS Reference Code + + Copyright (c) 2006 - 2014, Intel Corporation + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + Filename: CPU1CST.ASL + + Revision: Refer to Readme + + Date: Refer to Readme + +-------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + This Processor Power Management BIOS Source Code is furnished under license + and may only be used or copied in accordance with the terms of the license. + The information in this document is furnished for informational use only, is + subject to change without notice, and should not be construed as a commitment + by Intel Corporation. Intel Corporation assumes no responsibility or liability + for any errors or inaccuracies that may appear in this document or any + software that may be provided in association with this document. + + Except as permitted by such license, no part of this document may be + reproduced, stored in a retrieval system, or transmitted in any form or by + any means without the express written consent of Intel Corporation. + + WARNING: You are authorized and licensed to install and use this BIOS code + ONLY on an IST PC. This utility may damage any system that does not + meet these requirements. + + An IST PC is a computer which + (1) Is capable of seamlessly and automatically transitioning among + multiple performance states (potentially operating at different + efficiency ratings) based upon power source changes, END user + preference, processor performance demand, and thermal conditions; and + (2) Includes an Intel Pentium II processors, Intel Pentium III + processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4 + Processor-M, Intel Pentium M Processor, or any other future Intel + processors that incorporates the capability to transition between + different performance states by altering some, or any combination of, + the following processor attributes: core voltage, core frequency, bus + frequency, number of processor cores available, or any other attribute + that changes the efficiency (instructions/unit time-power) at which the + processor operates. + +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + +NOTES: + (1) - IF the trap range and port definitions do not match those + specified by this reference code, this file must be modified IAW the + individual implmentation. + +-------------------------------------------------------------------------------- +------------------------------------------------------------------------------*/ + + +DefinitionBlock ( + "APCST.aml", + "SSDT", + 1, + "PmRef", + "ApCst", + 0x3000 + ) +{ +External(\_PR.CPU1, DeviceObj) +External(\_PR.CPU2, DeviceObj) +External(\_PR.CPU3, DeviceObj) +External(\_PR.CPU0._CST) + + Scope(\_PR.CPU1) + { + Method(_CST,0) + { + // + // Return P0's _CST object. + // + Return(\_PR.CPU0._CST) + } + } + + Scope(\_PR.CPU2) + { + Method(_CST,0) + { + // + // Return P0's _CST object. + // + Return(\_PR.CPU0._CST) + } + } + + Scope(\_PR.CPU3) + { + Method(_CST,0) + { + // + // Return P0's _CST object. + // + Return(\_PR.CPU0._CST) + } + } +} // End of Definition Block diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/ApIst.asl b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/ApIst.asl new file mode 100644 index 0000000000..1c894c2613 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/ApIst.asl @@ -0,0 +1,172 @@ +/*----------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + + Intel Silvermont Processor Power Management BIOS Reference Code + + Copyright (c) 2006 - 2014, Intel Corporation + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + Filename: APIST.ASL + + Revision: Refer to Readme + + Date: Refer to Readme + +-------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + This Processor Power Management BIOS Source Code is furnished under license + and may only be used or copied in accordance with the terms of the license. + The information in this document is furnished for informational use only, is + subject to change without notice, and should not be construed as a commitment + by Intel Corporation. Intel Corporation assumes no responsibility or liability + for any errors or inaccuracies that may appear in this document or any + software that may be provided in association with this document. + + Except as permitted by such license, no part of this document may be + reproduced, stored in a retrieval system, or transmitted in any form or by + any means without the express written consent of Intel Corporation. + + WARNING: You are authorized and licensed to install and use this BIOS code + ONLY on an IST PC. This utility may damage any system that does not + meet these requirements. + + An IST PC is a computer which + (1) Is capable of seamlessly and automatically transitioning among + multiple performance states (potentially operating at different + efficiency ratings) based upon power source changes, END user + preference, processor performance demand, and thermal conditions; and + (2) Includes an Intel Pentium II processors, Intel Pentium III + processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4 + Processor-M, Intel Pentium M Processor, or any other future Intel + processors that incorporates the capability to transition between + different performance states by altering some, or any combination of, + the following processor attributes: core voltage, core frequency, bus + frequency, number of processor cores available, or any other attribute + that changes the efficiency (instructions/unit time-power) at which the + processor operates. + +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + +NOTES: + (1) - IF the trap range and port definitions do not match those + specified by this reference code, this file must be modified IAW the + individual implmentation. + +-------------------------------------------------------------------------------- +------------------------------------------------------------------------------*/ + + +DefinitionBlock ( + "APIST.aml", + "SSDT", + 1, + "PmRef", + "ApIst", + 0x3000 + ) +{ + External(\_PR.CPU0._PSS, MethodObj) + External(\_PR.CPU0._PCT, MethodObj) + External(\_PR.CPU0._PPC, IntObj) + External(\_PR.CPU0._PSD, MethodObj) + External(\_PR.CPU1, DeviceObj) + External(\_PR.CPU2, DeviceObj) + External(\_PR.CPU3, DeviceObj) + External (CFGD) + External (PDC0) + + Scope(\_PR.CPU1) + { + Method(_PPC,0) + { + Return(\_PR.CPU0._PPC) // Return P0 _PPC value. + } + + Method(_PCT,0) + { + Return(\_PR.CPU0._PCT) // Return P0 _PCT. + } + + Method(_PSS,0) + { + //Return the same table as CPU0 for CMP cases. + Return(\_PR.CPU0._PSS) + } + + // The _PSD object provides information to the OSPM related + // to P-State coordination between processors in a multi-processor + // configurations. + // + Method(_PSD,0) + { + Return(\_PR.CPU0._PSD) // Return P0 _PSD. + } + } + + Scope(\_PR.CPU2) + { + Method(_PPC,0) + { + Return(\_PR.CPU0._PPC) // Return P0 _PPC value. + } + + Method(_PCT,0) + { + Return(\_PR.CPU0._PCT) // Return P0 _PCT. + } + + Method(_PSS,0) + { + //Return the same table as CPU0 for CMP cases. + Return(\_PR.CPU0._PSS) + } + + // The _PSD object provides information to the OSPM related + // to P-State coordination between processors in a multi-processor + // configurations. + // + Method(_PSD,0) + { + Return(\_PR.CPU0._PSD) // Return P0 _PSD. + } + } + + Scope(\_PR.CPU3) + { + Method(_PPC,0) + { + Return(\_PR.CPU0._PPC) // Return P0 _PPC value. + } + + Method(_PCT,0) + { + Return(\_PR.CPU0._PCT) // Return P0 _PCT. + } + + Method(_PSS,0) + { + //Return the same table as CPU0 for CMP cases. + Return(\_PR.CPU0._PSS) + } + + // The _PSD object provides information to the OSPM related + // to P-State coordination between processors in a multi-processor + // configurations. + // + Method(_PSD,0) + { + Return(\_PR.CPU0._PSD) // Return P0 _PSD. + } + } +} // End of Definition Block diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/ApTst.asl b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/ApTst.asl new file mode 100644 index 0000000000..266f8465fe --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/ApTst.asl @@ -0,0 +1,268 @@ +/*----------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + + Intel Platform Processor Power Management BIOS Reference Code + + Copyright (c) 2007 - 2014, Intel Corporation + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + Filename: APTST.ASL + + Revision: Refer to Readme + + Date: Refer to Readme + +-------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + This Processor Power Management BIOS Source Code is furnished under license + and may only be used or copied in accordance with the terms of the license. + The information in this document is furnished for informational use only, is + subject to change without notice, and should not be construed as a commitment + by Intel Corporation. Intel Corporation assumes no responsibility or liability + for any errors or inaccuracies that may appear in this document or any + software that may be provided in association with this document. + + Except as permitted by such license, no part of this document may be + reproduced, stored in a retrieval system, or transmitted in any form or by + any means without the express written consent of Intel Corporation. + + WARNING: You are authorized and licensed to install and use this BIOS code + ONLY on an IST PC. This utility may damage any system that does not + meet these requirements. + + An IST PC is a computer which + (1) Is capable of seamlessly and automatically transitioning among + multiple performance states (potentially operating at different + efficiency ratings) based upon power source changes, END user + preference, processor performance demand, and thermal conditions; and + (2) Includes an Intel Pentium II processors, Intel Pentium III + processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4 + Processor-M, Intel Pentium M Processor, or any other future Intel + processors that incorporates the capability to transition between + different performance states by altering some, or any combination of, + the following processor attributes: core voltage, core frequency, bus + frequency, number of processor cores available, or any other attribute + that changes the efficiency (instructions/unit time-power) at which the + processor operates. + +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + +NOTES: + (1) - IF the trap range and port definitions do not match those + specified by this reference code, this file must be modified IAW the + individual implmentation. + +-------------------------------------------------------------------------------- +------------------------------------------------------------------------------*/ + + +DefinitionBlock( + "APTST.aml", + "SSDT", + 0x01, + "PmRef", + "ApTst", + 0x3000 + ) +{ + External(\_PR.CPU1, DeviceObj) + External(\_PR.CPU2, DeviceObj) + External(\_PR.CPU3, DeviceObj) + External(\_PR.CPU0._PTC) + External(\_PR.CPU0._TSS) + External(PDC0) + External(CFGD) + External(MPEN) + + Scope(\_PR.CPU1) + { + Name(_TPC, 0) // All T-States are available + + // + // T-State Control/Status interface + // + Method(_PTC, 0) + { + Return(\_PR.CPU0._PTC) + } + + Method(_TSS, 0) + { + Return(\_PR.CPU0._TSS) + } + + // + // T-State Dependency + // + Method(_TSD, 0) + { + // + // IF four cores are supported/enabled && !(direct access to MSR) + // Report 4 processors and SW_ANY as the coordination + // IF two cores are supported/enabled && !(direct access to MSR) + // Report 2 processors and SW_ANY as the coordination type + // ELSE + // Report 1 processor and SW_ALL as the coordination type (domain 1) + // + // CFGD[23] = Four cores enabled + // CFGD[24] = Two or more cores enabled + // PDCx[2] = OSPM is capable of direct access to On + // Demand throttling MSR + // + + If(LNot(And(PDC0,4))) + { + Return(Package(){ // SW_ANY + Package(){ + 5, // # entries. + 0, // Revision. + 0, // Domain #. + 0xFD, // Coord Type- SW_ANY + MPEN // # processors. + } + }) + } + Return(Package(){ // SW_ALL + Package(){ + 5, // # entries. + 0, // Revision. + 1, // Domain #. + 0xFC, // Coord Type- SW_ALL + 1 // # processors. + } + }) + } + } // End of CPU1 + + Scope(\_PR.CPU2) + { + Name(_TPC, 0) // All T-States are available + + // + // T-State Control/Status interface + // + Method(_PTC, 0) + { + Return(\_PR.CPU0._PTC) + } + + Method(_TSS, 0) + { + Return(\_PR.CPU0._TSS) + } + + // + // T-State Dependency + // + Method(_TSD, 0) + { + // + // IF four cores are supported/enabled && !(direct access to MSR) + // Report 4 processors and SW_ANY as the coordination + // IF two cores are supported/enabled && !(direct access to MSR) + // Report 2 processors and SW_ANY as the coordination type + // ELSE + // Report 1 processor and SW_ALL as the coordination type (domain 1) + // + // CFGD[23] = Four cores enabled + // CFGD[24] = Two or more cores enabled + // PDCx[2] = OSPM is capable of direct access to On + // Demand throttling MSR + // + + If(LNot(And(PDC0,4))) + { + Return(Package(){ // SW_ANY + Package(){ + 5, // # entries. + 0, // Revision. + 0, // Domain #. + 0xFD, // Coord Type- SW_ANY + MPEN // # processors. + } + }) + } + Return(Package(){ // SW_ALL + Package(){ + 5, // # entries. + 0, // Revision. + 1, // Domain #. + 0xFC, // Coord Type- SW_ALL + 1 // # processors. + } + }) + } + } // End of CPU2 + + Scope(\_PR.CPU3) + { + Name(_TPC, 0) // All T-States are available + + // + // T-State Control/Status interface + // + Method(_PTC, 0) + { + Return(\_PR.CPU0._PTC) + } + + Method(_TSS, 0) + { + Return(\_PR.CPU0._TSS) + } + + // + // T-State Dependency + // + Method(_TSD, 0) + { + // + // IF four cores are supported/enabled && !(direct access to MSR) + // Report 4 processors and SW_ANY as the coordination + // IF two cores are supported/enabled && !(direct access to MSR) + // Report 2 processors and SW_ANY as the coordination type + // ELSE + // Report 1 processor and SW_ALL as the coordination type (domain 1) + // + // CFGD[23] = Four cores enabled + // CFGD[24] = Two or more cores enabled + // PDCx[2] = OSPM is capable of direct access to On + // Demand throttling MSR + // + + If(LNot(And(PDC0,4))) + { + Return(Package(){ // SW_ANY + Package(){ + 5, // # entries. + 0, // Revision. + 0, // Domain #. + 0xFD, // Coord Type- SW_ANY + MPEN // # processors. + } + }) + } + Return(Package(){ // SW_ALL + Package(){ + 5, // # entries. + 0, // Revision. + 1, // Domain #. + 0xFC, // Coord Type- SW_ALL + 1 // # processors. + } + }) + } + } // End of CPU3 +} // End of Definition Block + diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/Cpu0Cst.asl b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/Cpu0Cst.asl new file mode 100644 index 0000000000..1267d98ec3 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/Cpu0Cst.asl @@ -0,0 +1,280 @@ + +/*----------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + + Intel Silvermont Processor Power Management BIOS Reference Code + + Copyright (c) 2006 - 2014, Intel Corporation + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + Filename: CPU0CST.ASL + + Revision: Refer to Readme + + Date: Refer to Readme + +-------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + This Processor Power Management BIOS Source Code is furnished under license + and may only be used or copied in accordance with the terms of the license. + The information in this document is furnished for informational use only, is + subject to change without notice, and should not be construed as a commitment + by Intel Corporation. Intel Corporation assumes no responsibility or liability + for any errors or inaccuracies that may appear in this document or any + software that may be provided in association with this document. + + Except as permitted by such license, no part of this document may be + reproduced, stored in a retrieval system, or transmitted in any form or by + any means without the express written consent of Intel Corporation. + + WARNING: You are authorized and licensed to install and use this BIOS code + ONLY on an IST PC. This utility may damage any system that does not + meet these requirements. + + An IST PC is a computer which + (1) Is capable of seamlessly and automatically transitioning among + multiple performance states (potentially operating at different + efficiency ratings) based upon power source changes, END user + preference, processor performance demand, and thermal conditions; and + (2) Includes an Intel Pentium II processors, Intel Pentium III + processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4 + Processor-M, Intel Pentium M Processor, or any other future Intel + processors that incorporates the capability to transition between + different performance states by altering some, or any combination of, + the following processor attributes: core voltage, core frequency, bus + frequency, number of processor cores available, or any other attribute + that changes the efficiency (instructions/unit time-power) at which the + processor operates. + +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + +NOTES: + (1) - IF the trap range and port definitions do not match those + specified by this reference code, this file must be modified IAW the + individual implmentation. + +-------------------------------------------------------------------------------- +------------------------------------------------------------------------------*/ + + +DefinitionBlock ( + "CPU0CST.aml", + "SSDT", + 1, + "PmRef", + "Cpu0Cst", + 0x3001 + ) +{ + External(\_PR.CPU0, DeviceObj) + External(PWRS) + External(CFGD) + External(PDC0) + + Scope(\_PR.CPU0) + { + OperationRegion (DEB0, SystemIO, 0x80, 1) //DBG + Field (DEB0, ByteAcc,NoLock,Preserve) //DBG + { DBG8, 8,} //DBG + + Method (_CST, 0) + { + Store(0x60,DBG8) //DBG + + // IF CMP is supported, but independent C-States beyond C1 are + // not supported; return C1 Halt and rely on BIOS based software + // coordination + // + // CFGD[24] = CMP support + // PDCx[4] = 0 - OS does not support ind. C2/C3 in MP systems + // + // Note: SMI will be generated when both processor enter the + // Halt state. + // + If(LAnd(And(CFGD,0x01000000), LNot(And(PDC0,0x10)))) + { + Store(0x61,DBG8) //DBG + Return(Package() { + 1, + Package() + { // C1 halt, but with BIOS coordination + ResourceTemplate(){Register(FFixedHW, 0, 0, 0)}, + 1, + 157, + 1000 + } + }) + } + + // IF MWAIT extensions are supported, use them. + // + // IF C6 capable/enabled AND Battery + // Report MWAIT C1, C2, C6 w/ BM_STS avoidance + // ELSE IF C4 capable/enabled AND Battery + // Report MWAIT C1, C2, C4 w/ BM_STS avoidance + // ELSE IF C3 capable/enabled + // Report MWAIT C1, C2, C3 w/ BM_STS avoidance + // ELSE IF C2 capable/enabled + // Report MWAIT C1, C2 + // ELSE + // Report MWAIT C1 + // + // CFGD[21] = 1 - MWAIT extensions supported + // CFGD[13] = 1 - C7 Capable/Enabled + // CFGD[12] = 1 - C6S Capable/Enabled + // CFGD[11] = 1 - C6 Capable/Enabled + // CFGD[7] = 1 - C4 Capable/Enabled + // CFGD[5] = 1 - C3 Capable/Enabled + // PDCx[9] = 1 - OS supports MWAIT extensions + // PDCx[8] = 1 - OS supports MWAIT for C1 + // (Inferred from PDCx[9] = 1.) + // PDCx[4] = 1 - OS supports independent C2/C3 in MP systems + // or + // NOT CMP (Inferred from previous check.) + // + If(LAnd(And(CFGD, 0x200000), And(PDC0,0x200))) + { + // + // The implementor may wish to only report C1-C2 + // when on AC power. In this case, the IF clause below can + // be modified to something like: + // + // "If(LAnd(And(CFGD,0x200), LNot(PWRS)))" + // + // Which uses the power state of the system (PWRS) to + // determine whether to allow deepers states. + // + // IF C7 supported AND on battery + // report MWAIT C1, C6, C7 + // + // CFGD[13] = C7 Capable/Enabled + // CFGD[11] = C6 Capable/Enabled + // + If(LAnd(And(CFGD,0x2000),And(CFGD,0x40000000))) + { + Store(0x77,DBG8) //DBG + Return( Package() + { + 3, + Package() + { // C1, MWAIT + ResourceTemplate(){Register(FFixedHW, 1, 2, 0x00, 1)}, + 1, + 1, + 1000 + }, + Package() + { + // C6, MWAIT Extension with Incremental L2 Shrink + // ResourceTemplate(){Register(FFixedHW, 1, 2, 0x50, 1)}, + // C6, MWAIT Extension with No L2 Shrink + ResourceTemplate(){Register(FFixedHW, 1, 2, 0x51, 1)}, + 2, + 500, + 10 + }, + Package() + { + // C7, MWAIT Extension with Full L2 Shrink + ResourceTemplate(){Register(FFixedHW, 1, 2, 0x64, 1)}, + 3, + 1500, //PnP setting, 1.5 ms for worst-case exit latency + 10 + } + }) + } + + + If(LAnd(And(CFGD,0x2000),LNot(And(CFGD,0x40000000)))) + { + Store(0x67,DBG8) //DBG + Return( Package() + { + 3, + Package() + { // C1, MWAIT + ResourceTemplate(){Register(FFixedHW, 1, 2, 0x00, 1)}, + 1, + 1, + 1000 + }, + Package() + { + // C6, MWAIT Extension with Incremental L2 Shrink + // ResourceTemplate(){Register(FFixedHW, 1, 2, 0x50, 1)}, + // C6 = C6NS, MWAIT Extension with No L2 Shrink + ResourceTemplate(){Register(FFixedHW, 1, 2, 0x51, 1)}, + 2, + 500, + 10 + }, + Package() + { + + ResourceTemplate(){Register(FFixedHW, 1, 2, 0x52, 1)}, + 3, + 1500, //PnP setting, 1.5 ms for worst-case exit latency + 10 + } + }) + } + + If(And(CFGD,0x800)) // Setup Max C-State = C6 + { + Store(0x76,DBG8) //DBG + Return( Package() + { + 2, + Package() + { // C1, MWAIT + ResourceTemplate(){Register(FFixedHW, 1, 2, 0x00, 1)}, + 1, + 1, + 1000 + }, + Package() + { + // C6, MWAIT Extension with Incremental L2 Shrink + // ResourceTemplate(){Register(FFixedHW, 1, 2, 0x50, 1)}, + // C6, MWAIT Extension with No L2 Shrink + ResourceTemplate(){Register(FFixedHW, 1, 2, 0x51, 1)}, + 2, + 500, + 10 + } + }) + } + // + // IF no deeper C-States are supported; report MWAIT C1. + // + Store(0x71,DBG8) //DBG + Return(Package() + { + 1, + Package() + { // C1, MWAIT + ResourceTemplate () {Register(FFixedHW, 1, 2, 0x00, 1)}, + 1, + 1, + 1000 + } + }) + } + + + } + } +} + + diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/Cpu0Ist.asl b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/Cpu0Ist.asl new file mode 100644 index 0000000000..8bb45124d5 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/Cpu0Ist.asl @@ -0,0 +1,266 @@ +/*----------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + + Intel Silvermont Processor Power Management BIOS Reference Code + + Copyright (c) 2006 - 2014, Intel Corporation + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + Filename: CPU0IST.ASL + + Revision: Refer to Readme + + Date: Refer to Readme + +-------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + This Processor Power Management BIOS Source Code is furnished under license + and may only be used or copied in accordance with the terms of the license. + The information in this document is furnished for informational use only, is + subject to change without notice, and should not be construed as a commitment + by Intel Corporation. Intel Corporation assumes no responsibility or liability + for any errors or inaccuracies that may appear in this document or any + software that may be provided in association with this document. + + Except as permitted by such license, no part of this document may be + reproduced, stored in a retrieval system, or transmitted in any form or by + any means without the express written consent of Intel Corporation. + + WARNING: You are authorized and licensed to install and use this BIOS code + ONLY on an IST PC. This utility may damage any system that does not + meet these requirements. + + An IST PC is a computer which + (1) Is capable of seamlessly and automatically transitioning among + multiple performance states (potentially operating at different + efficiency ratings) based upon power source changes, END user + preference, processor performance demand, and thermal conditions; and + (2) Includes an Intel Pentium II processors, Intel Pentium III + processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4 + Processor-M, Intel Pentium M Processor, or any other future Intel + processors that incorporates the capability to transition between + different performance states by altering some, or any combination of, + the following processor attributes: core voltage, core frequency, bus + frequency, number of processor cores available, or any other attribute + that changes the efficiency (instructions/unit time-power) at which the + processor operates. + +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + +NOTES: + (1) - IF the trap range and port definitions do not match those + specified by this reference code, this file must be modified IAW the + individual implmentation. + +-------------------------------------------------------------------------------- +------------------------------------------------------------------------------*/ + + +DefinitionBlock ( + "CPU0IST.aml", + "SSDT", + 0x01, + "PmRef", + "Cpu0Ist", + 0x3000 + ) +{ + External (\_PR.CPU0, DeviceObj) + External (PDC0) + External (CFGD) + + Scope(\_PR.CPU0) + { + //OperationRegion (DEB0, SystemIO, 0x80, 1) //DBG + //Field (DEB0, ByteAcc,NoLock,Preserve) //DBG + //{ DBG8, 8,} //DBG + + Name(_PPC, 0) // Initialize as All States Available. + + // NOTE: For CMP systems; this table is not loaded unless + // the required driver support is present. + // So, we do not check for those cases here. + // + // CFGD[0] = GV3 Capable/Enabled + // PDCx[0] = OS Capable of Hardware P-State control + // + Method(_PCT,0) + { + If(LAnd(And(CFGD,0x0001), And(PDC0,0x0001))) + { + //Store(0xA0,DBG8) //DBG + Return(Package() // Native Mode + { + ResourceTemplate(){Register(FfixedHW, 0, 0, 0)}, + ResourceTemplate(){Register(FfixedHW, 0, 0, 0)} + }) + } + // @NOTE: IO Trap is not supported. Therefore should not expose any IO interface for _PCT + // For all other cases, report control through the + // SMI interface. (The port used for SMM control is fixed up + // by the initialization code.) + // + Return(Package() // SMM Mode + { + ResourceTemplate(){Register(FfixedHW, 0, 0, 0)}, + ResourceTemplate(){Register(FfixedHW, 0, 0, 0)} + }) + } + + + // NOTE: For CMP systems; this table is not loaded if MP + // driver support is not present or P-State are disabled. + // + Method(_PSS,0) + { + // + // Report NSPP if: + // (1) GV3 capable (Not checked, see above.) + // (2) Driver support direct hardware control + // (3) MP driver support present (Not checked, see above.) + // else; + // Report SPSS + // + // PDCx[0] = OS Capable of Hardware P-State control + // + If(And(PDC0,0x0001)){ + //Store(0xB0,DBG8) //DBG + Return(NPSS) + } + //Store(0xBF,DBG8) //DBG + // Otherwise, report SMM mode + // + 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}, + 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}, + 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} + }) + + // The _PSD object provides information to the OSPM related + // to P-State coordination between processors in a multi-processor + // configurations. + // + Method(_PSD,0) + { + // + // IF CMP is supported/enabled + // IF quad core processor + // IF PDC[11] + // Report 4 processors and HW_ALL as the coordination type + // ELSE + // Report 4 processors and SW_ALL as the coordination type + // ELSE + // IF PDC[11] + // Report 2 processors and HW_ALL as the coordination type + // ELSE + // Report 2 processors and SW_ALL as the coordination type + // ELSE + // Report 1 processor and SW_ALL as the coordination type + // (Domain 0) + // + // CFGD[24] = Two or more cores enabled + // CFGD[23] = Four cores enabled + // PDCx[11] = Hardware coordination with hardware feedback + // + + If(And(CFGD,0x1000000)) // CMP Enabled. + { + If(And(CFGD,0x800000)) // 2 or 4 process. + { + If(And(PDC0,0x0800)) + { + Return(Package(){ // HW_ALL + Package(){ + 5, // # entries. + 0, // Revision. + 0, // Domain #. + 0xFE, // Coord Type- HW_ALL. + 4 // # processors. + } + }) + } // If(And(PDC0,0x0800)) + Return(Package(){ // SW_ALL + Package(){ + 5, // # entries. + 0, // Revision. + 0, // Domain #. + 0xFC, // Coord Type- SW_ALL. + 4 // # processors. + } + }) + } else { + Return(Package(){ // HW_ALL + Package(){ + 5, // # entries. + 0, // Revision. + 0, // Domain #. + 0xFE, // Coord Type- HW_ALL. + 2 // # processors. + } + }) + } + } // If(And(CFGD,0x1000000)) // CMP Enabled. + + Return(Package(){ // SW_ALL + Package(){ + 5, // # entries. + 0, // Revision. + 0, // Domain #. + 0xFC, // Coord Type- SW_ALL. + 1 // # processors. + } + }) + } // Method(_PSD,0) + } // Scope(\_PR.CPU0) +} // End of Definition Block + + diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/Cpu0Tst.asl b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/Cpu0Tst.asl new file mode 100644 index 0000000000..e535c93c3a --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/Cpu0Tst.asl @@ -0,0 +1,241 @@ +/*----------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + + Intel Silvermont Processor Power Management BIOS Reference Code + + Copyright (c) 2006 - 2014, Intel Corporation + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + Filename: CPU0TST.ASL + + Revision: Refer to Readme + + Date: Refer to Readme + +-------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + + This Processor Power Management BIOS Source Code is furnished under license + and may only be used or copied in accordance with the terms of the license. + The information in this document is furnished for informational use only, is + subject to change without notice, and should not be construed as a commitment + by Intel Corporation. Intel Corporation assumes no responsibility or liability + for any errors or inaccuracies that may appear in this document or any + software that may be provided in association with this document. + + Except as permitted by such license, no part of this document may be + reproduced, stored in a retrieval system, or transmitted in any form or by + any means without the express written consent of Intel Corporation. + + WARNING: You are authorized and licensed to install and use this BIOS code + ONLY on an IST PC. This utility may damage any system that does not + meet these requirements. + + An IST PC is a computer which + (1) Is capable of seamlessly and automatically transitioning among + multiple performance states (potentially operating at different + efficiency ratings) based upon power source changes, end user + preference, processor performance demand, and thermal conditions; and + (2) Includes an Intel Pentium II processors, Intel Pentium III + processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4 + Processor-M, Intel Pentium M Processor, or any other future Intel + processors that incorporates the capability to transition between + different performance states by altering some, or any combination of, + the following processor attributes: core voltage, core frequency, bus + frequency, number of processor cores available, or any other attribute + that changes the efficiency (instructions/unit time-power) at which the + processor operates. + +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- + +NOTES: + (1) - IF the trap range and port definitions do not match those + specified by this reference code, this file must be modified IAW the + individual implmentation. + +-------------------------------------------------------------------------------- +------------------------------------------------------------------------------*/ + +DefinitionBlock( + "CPU0TST.aml", + "SSDT", + 0x01, + "PmRef", + "Cpu0Tst", + 0x3000 + ) +{ + External(\_PR.CPU0, DeviceObj) + External(PDC0) + External(CFGD) + External(_PSS) + + Scope(\_PR.CPU0) + { + Name(_TPC, 0) // All T-States are available + + // + // T-State Control/Status interface + // + Method(_PTC, 0) + { + // + // IF OSPM is capable of direct access to MSR + // Report MSR interface + // ELSE + // Report I/O interface + // + // PDCx[2] = OSPM is capable of direct access to On + // Demand throttling MSR + // + If(And(PDC0, 0x0004)) { + Return(Package() { + ResourceTemplate(){Register(FFixedHW, 0, 0, 0)}, + ResourceTemplate(){Register(FFixedHW, 0, 0, 0)} + }) + } + + } + + // _TSS package for I/O port based T-State control + // "Power" fields are replaced with real values by the first + // call of _TSS method. + // + Name(TSSI, Package() { + Package(){100, 1000, 0, 0x00, 0}, + Package(){ 88, 875, 0, 0x0F, 0}, + Package(){ 75, 750, 0, 0x0E, 0}, + Package(){ 63, 625, 0, 0x0D, 0}, + Package(){ 50, 500, 0, 0x0C, 0}, + Package(){ 38, 375, 0, 0x0B, 0}, + Package(){ 25, 250, 0, 0x0A, 0}, + Package(){ 13, 125, 0, 0x09, 0} + }) + + // _TSS package for MSR based T-State control + // "Power" fields are replaced with real values by the first + // call of _TSS method. + // + Name(TSSM, Package() { + Package(){100, 1000, 0, 0x00, 0}, + Package(){ 88, 875, 0, 0x1E, 0}, + Package(){ 75, 750, 0, 0x1C, 0}, + Package(){ 63, 625, 0, 0x1A, 0}, + Package(){ 50, 500, 0, 0x18, 0}, + Package(){ 38, 375, 0, 0x16, 0}, + Package(){ 25, 250, 0, 0x14, 0}, + Package(){ 13, 125, 0, 0x12, 0} + }) + + Name(TSSF, 0) // Flag for TSSI/TSSM initialization + + Method(_TSS, 0) + { + // Update "Power" fields of TSSI/TSSM with the LFM + // power data IF _PSS is available + // + IF (LAnd(LNot(TSSF),CondRefOf(_PSS))) + { + Store(_PSS, Local0) + Store(SizeOf(Local0), Local1) // _PSS size + Decrement(Local1) // Index of LFM + Store(DerefOf(Index(DerefOf(Index(Local0,Local1)),1)), Local2) // LFM Power + + Store(0, Local3) + While(LLess(Local3, SizeOf(TSSI))) + { + Store(Divide(Multiply(Local2, Subtract(8, Local3)), 8), + Local4) // Power for this TSSI/TSSM entry + Store(Local4,Index(DerefOf(Index(TSSI,Local3)),1)) + Store(Local4,Index(DerefOf(Index(TSSM,Local3)),1)) + Increment(Local3) + } + Store(Ones, TSSF) // TSSI/TSSM are updated + } + // + // IF OSPM is capable of direct access to MSR + // Report TSSM + // ELSE + // Report TSSI + // + If(And(PDC0, 0x0004)) + { + Return(TSSM) + } + Return(TSSI) + } + + Method(_TDL, 0) + { + Store ("Cpu0: _TDL Called", Debug) + Name ( LFMI, 0) + Store (SizeOf(TSSM), LFMI) + Decrement(LFMI) // Index of LFM entry in TSSM + Return(LFMI) + } + + // + // T-State Dependency + // + Method(_TSD, 0) + { + // + // IF four cores are supported/enabled && !(direct access to MSR) + // Report 4 processors and SW_ANY as the coordination type + // ELSE IF two cores are supported/enabled && !(direct access to MSR) + // Report 2 processors and SW_ANY as the coordination type + // ELSE + // Report 1 processor and SW_ALL as the coordination type + // + // CFGD[23] = Four cores enabled + // CFGD[24] = Two or more cores enabled + // PDCx[2] = OSPM is capable of direct access to On + // Demand throttling MSR + // + If(LAnd(And(CFGD,0x0800000),LNot(And(PDC0,4)))) + { + Return(Package(){ // SW_ANY + Package(){ + 5, // # entries. + 0, // Revision. + 0, // Domain #. + 0xFD, // Coord Type- SW_ANY + 4 // # processors. + } + }) + } + If(LAnd(And(CFGD,0x1000000),LNot(And(PDC0,4)))) + { + Return(Package(){ // SW_ANY + Package(){ + 5, // # entries. + 0, // Revision. + 0, // Domain #. + 0xFD, // Coord Type- SW_ANY + 2 // # processors. + } + }) + } + Return(Package(){ // SW_ALL + Package(){ + 5, // # entries. + 0, // Revision. + 0, // Domain #. + 0xFC, // Coord Type- SW_ALL + 1 // # processors. + } + }) + } + } +} // End of Definition Block + diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/CpuPm.asl b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/CpuPm.asl new file mode 100644 index 0000000000..32cdcd354f --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/Ssdt/CpuPm.asl @@ -0,0 +1,799 @@ +/*----------------------------------------------------------------------------- + + + Intel Silvermont Processor Power Management BIOS Reference Code + + Copyright (c) 2006 - 2014, Intel Corporation + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + Filename: CPUPM.ASL + + Revision: Refer to Readme + + Date: Refer to Readme +------------------------------------------------------------------------------- + + This Processor Power Management BIOS Source Code is furnished under license + and may only be used or copied in accordance with the terms of the license. + The information in this document is furnished for informational use only, is + subject to change without notice, and should not be construed as a commitment + by Intel Corporation. Intel Corporation assumes no responsibility or liability + for any errors or inaccuracies that may appear in this document or any + software that may be provided in association with this document. + + Except as permitted by such license, no part of this document may be + reproduced, stored in a retrieval system, or transmitted in any form or by + any means without the express written consent of Intel Corporation. + + WARNING: You are authorized and licensed to install and use this BIOS code + ONLY on an IST PC. This utility may damage any system that does not + meet these requirements. + + An IST PC is a computer which + (1) Is capable of seamlessly and automatically transitioning among + multiple performance states (potentially operating at different + efficiency ratings) based upon power source changes, END user + preference, processor performance demand, and thermal conditions; and + (2) Includes an Intel Pentium II processors, Intel Pentium III + processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4 + Processor-M, Intel Pentium M Processor, or any other future Intel + processors that incorporates the capability to transition between + different performance states by altering some, or any combination of, + the following processor attributes: core voltage, core frequency, bus + frequency, number of processor cores available, or any other attribute + that changes the efficiency (instructions/unit time-power) at which the + processor operates. +------------------------------------------------------------------------------- + +NOTES: + (1) - Except for the SSDT package, the objects in this ASL code + may be moved to the DSDT. It is kept separate in this reference package + for ease of distribution only. +------------------------------------------------------------------------------*/ + +DefinitionBlock ( + "CPUPM.aml", + "SSDT", + 0x01, + "PmRef", + "CpuPm", + 0x3000 + ) +{ + External(\_PR.CPU0, DeviceObj) + External(\_PR.CPU1, DeviceObj) + External(\_PR.CPU2, DeviceObj) + External(\_PR.CPU3, DeviceObj) + External(SMIF) + + Scope(\) + { + + // Package of pointers to SSDT's + // + // First column is SSDT name, used for debug only. + // (First column must be EXACTLY eight characters.) + // Second column is physical address. + // Third column is table length. + // + // IF modifying this file, see warnings listed in ppminit.asm. + // + Name(SSDT,Package() + { + "CPU0IST ", 0x80000000, 0x80000000, + "APIST ", 0x80000000, 0x80000000, + "CPU0CST ", 0x80000000, 0x80000000, + "APCST ", 0x80000000, 0x80000000 + }) + + // + // Note: See PpmBiosInit in PPMINIT.ASM for a definition of + // the PpmFlags mirrored in CFGD. + // + Name(CFGD, 0x80000000) + + Name(\PDC0,0x80000000) // CPU0 _PDC Flags. + Name(\PDC1,0x80000000) // CPU1 _PDC Flags. + Name(\PDC2,0x80000000) // CPU2 _PDC Flags. + Name(\PDC3,0x80000000) // CPU3 _PDC Flags. + Name(\SDTL,0x00) // Loaded SSDT Flags. + } + + Scope(\_PR.CPU0) + { + // + // Define handles for opregions (used by load.) + // + Name(HI0,0) // Handle to CPU0IST + Name(HC0,0) // Handle to CPU0CST + + Method(_PDC,1) + { + // + // Check and extract the _PDC information. + // + Store(CPDC(Arg0), Local0) + // + // Save the capability information and load tables as needed. + // + GCAP(Local0) + // + // Return status. + // + //Return (Local0) + } + + Method(_OSC, 4) + { + // + // Check and extract the _OSC information. + // + Store(COSC(Arg0, Arg1, Arg2, Arg3), Local0) + // + // Save the capability information and load tables as needed. + // + GCAP(Local0) + // + // Return status. + // + Return (Local0) + } + + // + // Implement a generic Method to check _PDC information which may be called + // by any of the processor scopes. (The use of _PDC is deprecated in ACPI 3. + // in favor of _OSC. However, for backwards compatibility, _PDC may be + // implemented using _OSC as follows:) + // + Method(CPDC,1) + { + CreateDwordField (Arg0, 0, REVS) + CreateDwordField (Arg0, 4, SIZE) + + // + // Local0 = Number of bytes for Arg0 + // + Store (SizeOf (Arg0), Local0) + + // + // Local1 = Number of Capabilities bytes in Arg0 + // + Store (Subtract (Local0, 8), Local1) + + // + // TEMP = Temporary field holding Capability DWORDs + // + CreateField (Arg0, 64, Multiply (Local1, 8), TEMP) + + // + // Create the Status (STAT) buffer with the first DWORD = 0 + // This is required as per ACPI 3.0 Spec which says the + // first DWORD is used to return errors defined by _OSC. + // + Name (STS0, Buffer () {0x00, 0x00, 0x00, 0x00}) + + // + // Concatenate the _PDC capabilities bytes to the STS0 Buffer + // and store them in a local variable for calling OSC + // + Concatenate (STS0, TEMP, Local2) + + Return(COSC (ToUUID("4077A616-290C-47BE-9EBD-D87058713953"), REVS, SIZE, Local2)) + } + + // + // Implement a generic Method to check _OSC information which may be called + // by any of the processor scopes. + // + Method(COSC, 4) + { + // + // Point to Status DWORD in the Arg3 buffer (STATUS) + // + CreateDWordField(Arg3, 0, STS0) + // + // Point to Caps DWORDs of the Arg3 buffer (CAPABILITIES) + // + CreateDwordField(Arg3, 4, CAP0) + + // + // _OSC needs to validate the UUID and Revision. + // + // IF Unrecognized UUID + // Return Unrecognized UUID _OSC Failure + // IF Unsupported Revision + // Return Unsupported Revision _OSC Failure + // + // STS0[0] = Reserved + // STS0[1] = _OSC Failure + // STS0[2] = Unrecognized UUID + // STS0[3] = Unsupported Revision + // STS0[4] = Capabilities masked + // + // Note: The comparison method used is necessary due to + // limitations of certain OSes which cannot perform direct + // buffer comparisons. + // + // Create a set of "Input" UUID fields. + // + CreateDwordField(Arg0, 0x0, IID0) + CreateDwordField(Arg0, 0x4, IID1) + CreateDwordField(Arg0, 0x8, IID2) + CreateDwordField(Arg0, 0xC, IID3) + // + // Create a set of "Expected" UUID fields. + // + Name(UID0, ToUUID("4077A616-290C-47BE-9EBD-D87058713953")) + CreateDwordField(UID0, 0x0, EID0) + CreateDwordField(UID0, 0x4, EID1) + CreateDwordField(UID0, 0x8, EID2) + CreateDwordField(UID0, 0xC, EID3) + // + // Verify the input UUID matches the expected UUID. + // + If(LNot(LAnd(LAnd(LEqual(IID0, EID0),LEqual(IID1, EID1)),LAnd(LEqual(IID2, EID2),LEqual(IID3, EID3))))) + { + // + // Return Unrecognized UUID _OSC Failure + // + Store (0x6, STS0) + Return (Arg3) + } + + If(LNot(LEqual(Arg1,1))) + { + // + // Return Unsupported Revision _OSC Failure + // + Store (0xA, STS0) + Return (Arg3) + } + + Return (Arg3) + } + + // + // Get the capability information and load appropriate tables as needed. + // + Method(GCAP, 1) + { + + // Point to Status DWORD in the Arg0 buffer (STATUS) + CreateDWordField(Arg0, 0, STS0) + + // Point to Caps DWORDs of the Arg0 buffer (CAPABILITIES) + CreateDwordField(Arg0, 4, CAP0) + + // + // If the UUID was unrecognized or the _OSC revision was unsupported, + // return without updating capabilities. + // + If(LOr(LEqual(STS0,0x6),LEqual(STS0,0xA))) + { + Return() + } + + // + // Check if this is a query (BIT0 of Status = 1). + // If so, mask off the bits we support and return. + // + if (And(STS0, 1)) + { + And(CAP0, 0xBFF, CAP0) + Return() + } + + // + // Store result of PDC. (We clear out the MSB, which was just + // used as a placeholder for the compiler; and then "OR" the + // value in case we get multiple calls, each of which only + // reports partial support.) + // + Or(And(PDC0, 0x7FFFFFFF), CAP0, PDC0) + + // + // Check IF the IST SSDTs should be loaded. + // + // CFGD[0] = GV3 Capable/Enabled + // + If(And(CFGD,0x01)) + { + // + // Load the IST SSDTs if: + // (1) CMP capable and enabled. + // (2) Driver supports P-States in MP configurations + // (3) Driver supports direct HW P-State control + // (4) SSDT is not already loaded + // + // CFGD[24] = Two or more cores enabled + // PDCx[3] = OS supports C1 and P-states in MP systems + // PDCx[0] = OS supports direct access of the perf MSR + // SDTL[0] = CPU0 IST SSDT Loaded + // + If(LAnd(LAnd(And(CFGD,0x01000000),LEqual(And(PDC0, 0x0009), 0x0009)),LNot(And(SDTL,0x01)))) + { + // + // Flag the IST SSDT as loaded for CPU0 + // + Or(SDTL, 0x01, SDTL) + + OperationRegion(IST0,SystemMemory,DeRefOf(Index(SSDT,1)),DeRefOf(Index(SSDT,2))) + Load(IST0, HI0) // Dynamically load the CPU0IST SSDT + } + } + + // + // Check IF the CST SSDTs should be loaded. + // + // CFGD[11,7,2,1] = C6, C4, C1E, C1 Capable/Enabled + // + If(And(CFGD,0x82)) + { + // + // Load the CST SSDTs if: + // (1) CMP capable/enabled + // (2) Driver supports multi-processor configurations + // (3) CPU0 CST ISDT is not already loaded + // + // CFGD[24] = Two or more cores enabled + // PDCx[3] = OS supports C1 and P-states in MP systems + // PDCx[4] = OS supports ind. C2/C3 in MP systems + // SDTL[1] = CPU0 CST SSDT Loaded + // + If(LAnd(LAnd(And(CFGD,0x01000000),And(PDC0,0x0018)),LNot(And(SDTL,0x02)))) + { + // + // Flag the CST SSDT as loaded for CPU0 + // + Or(SDTL, 0x02, SDTL) + + OperationRegion(CST0,SystemMemory,DeRefOf(Index(SSDT,7)),DeRefOf(Index(SSDT,8))) + Load(CST0, HC0) // Dynamically load the CPU0CST SSDT + } + } + + Return () + } + } + + + Scope(\_PR.CPU1) + { + // + // Define handles for opregions (used by load.) + // + Name(HI1,0) // Handle to APIST + Name(HC1,0) // Handle to APCST + + Method(_PDC,1) + { + // + // Refer to \_PR.CPU0._PDC for description. + // + Store(\_PR.CPU0.CPDC(Arg0), Local0) + GCAP(Local0) + //Return (Local0) + } + + Method(_OSC, 4) + { + // + // Refer to \_PR.CPU0._OSC for description. + // + Store(\_PR.CPU0.COSC(Arg0, Arg1, Arg2, Arg3), Local0) + GCAP(Local0) + Return (Local0) + } + + // + // Get the capability information and load appropriate tables as needed. + // + Method(GCAP, 1) + { + // + // Point to Status DWORD in the Arg0 buffer (STATUS) + // + CreateDWordField(Arg0, 0, STS1) + // + // Point to Caps DWORDs of the Arg0 buffer (CAPABILITIES) + // + CreateDwordField(Arg0, 4, CAP1) + // + // If the UUID was unrecognized or the _OSC revision was unsupported, + // return without updating capabilities. + // + If(LOr(LEqual(STS1,0x6),LEqual(STS1,0xA))) + { + Return() + } + + // + // Check if this is a query (BIT0 of Status = 1). + // If so, mask off the bits we support and return. + // + if (And(STS1, 1)) + { + And(CAP1, 0xBFF, CAP1) + Return() + } + + // + // Store result of PDC. (We clear out the MSB, which was just + // used as a placeholder for the compiler; and then "OR" the + // value in case we get multiple calls, each of which only + // reports partial support.) + // + Or(And(PDC1, 0x7FFFFFFF), CAP1, PDC1) + + // + // Attempt to dynamically load the IST SSDTs if: + // (1) Driver supports P-States in MP configurations + // (2) Driver supports direct HW P-State control + // + // PDCx[3] = OS supports C1 and P-states in MP systems + // PDCx[0] = OS supports direct access of the perf MSR + // + If(LEqual(And(PDC0, 0x0009), 0x0009)) + { + APPT() + } + + // + // Load the CST SSDTs if: + // (1) Driver supports multi-processor configurations + // + // PDCx[3] = OS supports C1 and P-states in MP systems + // PDCx[4] = OS supports ind. C2/C3 in MP systems + // + If(And(PDC0,0x0018)) + { + APCT() + } + + Return() + } + + // + // Dynamically load the CST SSDTs if: + // (1) C-States are enabled + // (2) SSDT is not already loaded + // + // CFGD[11,7,2,1] = C6, C4, C1E, C1 Capable/Enabled + // SDTL[5] = AP CST SSDT Loaded + // + Method(APCT,0) + { + If(LAnd(And(CFGD,0x82),LNot(And(SDTL,0x20)))) + { + // + // Flag the CST SSDT as loaded for the AP's + // + Or(SDTL, 0x20, SDTL) + // + // Dynamically load the APCST SSDT + // + OperationRegion(CST1,SystemMemory,DeRefOf(Index(SSDT,10)),DeRefOf(Index(SSDT,11))) + Load(CST1, HC1) + } + } + + // + // Dynamically load the IST SSDTs if: + // (1) If GV3 capable and enabled + // (2) SSDT is not already loaded + // + // CFGD[0] = GV3 Capable/Enabled + // SDTL[4] = AP IST SSDT Loaded + // + Method(APPT,0) + { + If(LAnd(And(CFGD,0x01),LNot(And(SDTL,0x10)))) + { + // + // Flag the IST SSDT as loaded for CPU0 + // + Or(SDTL, 0x10, SDTL) + + OperationRegion(IST1,SystemMemory,DeRefOf(Index(SSDT,4)),DeRefOf(Index(SSDT,5))) + Load(IST1, HI1) // Dynamically load the CPU1IST SSDT + } + } + } // End CPU1 + + Scope(\_PR.CPU2) + { + // + // Define handles for opregions (used by load.) + // + Name(HI1,0) // Handle to APIST + Name(HC1,0) // Handle to APCST + + Method(_PDC,1) + { + // + // Refer to \_PR.CPU0._PDC for description. + // + Store(\_PR.CPU0.CPDC(Arg0), Local0) + GCAP(Local0) + //Return (Local0) + } + + Method(_OSC, 4) + { + // + // Refer to \_PR.CPU0._OSC for description. + // + Store(\_PR.CPU0.COSC(Arg0, Arg1, Arg2, Arg3), Local0) + GCAP(Local0) + Return (Local0) + } + + // + // Get the capability information and load appropriate tables as needed. + // + Method(GCAP, 1) + { + // + // Point to Status DWORD in the Arg0 buffer (STATUS) + // + CreateDWordField(Arg0, 0, STS1) + // + // Point to Caps DWORDs of the Arg0 buffer (CAPABILITIES) + // + CreateDwordField(Arg0, 4, CAP1) + // + // If the UUID was unrecognized or the _OSC revision was unsupported, + // return without updating capabilities. + // + If(LOr(LEqual(STS1,0x6),LEqual(STS1,0xA))) + { + Return() + } + + // + // Check if this is a query (BIT0 of Status = 1). + // If so, mask off the bits we support and return. + // + if (And(STS1, 1)) + { + And(CAP1, 0xBFF, CAP1) + Return() + } + + // + // Store result of PDC. (We clear out the MSB, which was just + // used as a placeholder for the compiler; and then "OR" the + // value in case we get multiple calls, each of which only + // reports partial support.) + // + Or(And(PDC1, 0x7FFFFFFF), CAP1, PDC1) + + // + // Attempt to dynamically load the IST SSDTs if: + // (1) Driver supports P-States in MP configurations + // (2) Driver supports direct HW P-State control + // + // PDCx[3] = OS supports C1 and P-states in MP systems + // PDCx[0] = OS supports direct access of the perf MSR + // + If(LEqual(And(PDC0, 0x0009), 0x0009)) + { + APPT() + } + + // + // Load the CST SSDTs if: + // (1) Driver supports multi-processor configurations + // + // PDCx[3] = OS supports C1 and P-states in MP systems + // PDCx[4] = OS supports ind. C2/C3 in MP systems + // + If(And(PDC0,0x0018)) + { + APCT() + } + + Return() + } + + // + // Dynamically load the CST SSDTs if: + // (1) C-States are enabled + // (2) SSDT is not already loaded + // + // CFGD[11,7,2,1] = C6, C4, C1E, C1 Capable/Enabled + // SDTL[5] = AP CST SSDT Loaded + // + Method(APCT,0) + { + If(LAnd(And(CFGD,0x82),LNot(And(SDTL,0x20)))) + { + // + // Flag the CST SSDT as loaded for the AP's + // + Or(SDTL, 0x20, SDTL) + // + // Dynamically load the APCST SSDT + // + OperationRegion(CST1,SystemMemory,DeRefOf(Index(SSDT,10)),DeRefOf(Index(SSDT,11))) + Load(CST1, HC1) + } + } + + // + // Dynamically load the IST SSDTs if: + // (1) If GV3 capable and enabled + // (2) SSDT is not already loaded + // + // CFGD[0] = GV3 Capable/Enabled + // SDTL[4] = AP IST SSDT Loaded + // + Method(APPT,0) + { + If(LAnd(And(CFGD,0x01),LNot(And(SDTL,0x10)))) + { + // + // Flag the IST SSDT as loaded for CPU0 + // + Or(SDTL, 0x10, SDTL) + + OperationRegion(IST1,SystemMemory,DeRefOf(Index(SSDT,4)),DeRefOf(Index(SSDT,5))) + Load(IST1, HI1) // Dynamically load the CPU1IST SSDT + } + } + } // End CPU1 + + Scope(\_PR.CPU3) + { + // + // Define handles for opregions (used by load.) + // + Name(HI1,0) // Handle to APIST + Name(HC1,0) // Handle to APCST + + Method(_PDC,1) + { + // + // Refer to \_PR.CPU0._PDC for description. + // + Store(\_PR.CPU0.CPDC(Arg0), Local0) + GCAP(Local0) + //Return (Local0) + } + + Method(_OSC, 4) + { + // + // Refer to \_PR.CPU0._OSC for description. + // + Store(\_PR.CPU0.COSC(Arg0, Arg1, Arg2, Arg3), Local0) + GCAP(Local0) + Return (Local0) + } + + // + // Get the capability information and load appropriate tables as needed. + // + Method(GCAP, 1) + { + // + // Point to Status DWORD in the Arg0 buffer (STATUS) + // + CreateDWordField(Arg0, 0, STS1) + // + // Point to Caps DWORDs of the Arg0 buffer (CAPABILITIES) + // + CreateDwordField(Arg0, 4, CAP1) + // + // If the UUID was unrecognized or the _OSC revision was unsupported, + // return without updating capabilities. + // + If(LOr(LEqual(STS1,0x6),LEqual(STS1,0xA))) + { + Return() + } + + // + // Check if this is a query (BIT0 of Status = 1). + // If so, mask off the bits we support and return. + // + if (And(STS1, 1)) + { + And(CAP1, 0xBFF, CAP1) + Return() + } + + // + // Store result of PDC. (We clear out the MSB, which was just + // used as a placeholder for the compiler; and then "OR" the + // value in case we get multiple calls, each of which only + // reports partial support.) + // + Or(And(PDC1, 0x7FFFFFFF), CAP1, PDC1) + + // + // Attempt to dynamically load the IST SSDTs if: + // (1) Driver supports P-States in MP configurations + // (2) Driver supports direct HW P-State control + // + // PDCx[3] = OS supports C1 and P-states in MP systems + // PDCx[0] = OS supports direct access of the perf MSR + // + If(LEqual(And(PDC0, 0x0009), 0x0009)) + { + APPT() + } + + // + // Load the CST SSDTs if: + // (1) Driver supports multi-processor configurations + // + // PDCx[3] = OS supports C1 and P-states in MP systems + // PDCx[4] = OS supports ind. C2/C3 in MP systems + // + If(And(PDC0,0x0018)) + { + APCT() + } + + Return() + } + + // + // Dynamically load the CST SSDTs if: + // (1) C-States are enabled + // (2) SSDT is not already loaded + // + // CFGD[11,7,2,1] = C6, C4, C1E, C1 Capable/Enabled + // SDTL[5] = AP CST SSDT Loaded + // + Method(APCT,0) + { + If(LAnd(And(CFGD,0x82),LNot(And(SDTL,0x20)))) + { + // + // Flag the CST SSDT as loaded for the AP's + // + Or(SDTL, 0x20, SDTL) + // + // Dynamically load the APCST SSDT + // + OperationRegion(CST1,SystemMemory,DeRefOf(Index(SSDT,10)),DeRefOf(Index(SSDT,11))) + Load(CST1, HC1) + } + } + + // + // Dynamically load the IST SSDTs if: + // (1) If GV3 capable and enabled + // (2) SSDT is not already loaded + // + // CFGD[0] = GV3 Capable/Enabled + // SDTL[4] = AP IST SSDT Loaded + // + Method(APPT,0) + { + If(LAnd(And(CFGD,0x01),LNot(And(SDTL,0x10)))) + { + // + // Flag the IST SSDT as loaded for CPU0 + // + Or(SDTL, 0x10, SDTL) + + OperationRegion(IST1,SystemMemory,DeRefOf(Index(SSDT,4)),DeRefOf(Index(SSDT,5))) + Load(IST1, HI1) // Dynamically load the CPU1IST SSDT + } + } + } // End CPU3 +} // End of Definition Block + + + diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/PlatformBaseAddresses.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/PlatformBaseAddresses.h new file mode 100644 index 0000000000..43119b868a --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/PlatformBaseAddresses.h @@ -0,0 +1,98 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + + +Module Name: + + PlatformBaseAddresses.h + +Abstract: + + + +Revision History + +++*/ + + +#ifndef _PLATFORM_BASE_ADDRESSES_H +#define _PLATFORM_BASE_ADDRESSES_H + +// +// Define some fixed platform device location information +// + +// +// Define platform base +// + +// +// SIO +// +#define SIO_BASE_ADDRESS 0x0680 +#define SIO_MONITORING_BASE_ADDRESS 0x0290 +#define SIO_BASE_MASK 0xFFF0 +#define WINDBOND_ECIR_BASE_ADDRESS 0x0810 +#define SIO_MAILBOX_BASE_ADDRESS 0x0360 // Used by EC controller +#define SIO_EC_CHANNEL2 0x62 // Used by EC controller for offset 0x62 and 0x66 + + +// +// South Cluster +// +#define ACPI_BASE_ADDRESS 0x0400 +#define GPIO_BASE_ADDRESS 0x0500 +#define SMBUS_BUS_DEV_FUNC 0x1F0300 +#define SMBUS_BASE_ADDRESS 0xEFA0 // SMBus IO Base Address +#define SPI_BASE_ADDRESS 0xFED01000 // SPI Memory Base Address +#define PMC_BASE_ADDRESS 0xFED03000 // PMC Memory Base Address +#define SMBM_BASE_ADDRESS 0xFED04000 // SMBus Memory Base Address +#define IO_BASE_ADDRESS 0xFED0C000 // IO Memory Base Address +#define ILB_BASE_ADDRESS 0xFED08000 // ILB Memory Base Address +#define HPET_BASE_ADDRESS 0xFED00000 // HPET Base Address +#define RCBA_BASE_ADDRESS 0xFED1C000 // Root Complex Base Address +#define MPHY_BASE_ADDRESS 0xFEF00000 // MPHY Memory Base Address +#define PUNIT_BASE_ADDRESS 0xFED05000 // PUnit Memory Base Address + +// +// GPIO GROUP OFFSET +// +#define GPIO_SCORE_OFFSET 0x0000 +#define GPIO_NCORE_OFFSET 0x1000 +#define GPIO_SSUS_OFFSET 0x2000 + +// +// MCH/CPU +// +#define DMI_BASE_ADDRESS 0xFED18000 // 4K, similar to IIO_RCBA // modify from bearlake -- cchew10 +#define EP_BASE_ADDRESS 0xFED19000 +#define MC_MMIO_BASE 0xFED14000 // Base Address for MMIO registers + +// +// TPM +// +#define TPM_BASE_ADDRESS 0xFED40000 // Base address for TPM + +// +// Local and I/O APIC addresses. +// +#define IO_APIC_ADDRESS 0xFEC00000 +#define IIO_IOAPIC_ADDRESS 0xFEC90000 +#define LOCAL_APIC_ADDRESS 0xFEE00000 + + +#endif + + diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/Capsule.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/Capsule.h new file mode 100644 index 0000000000..618e3d35b1 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/Capsule.h @@ -0,0 +1,66 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Capsule.h + +Abstract: + + Capsule PPI definitions. + +--*/ +// +// +#ifndef _PEI_CAPSULE_PPI_H_ +#define _PEI_CAPSULE_PPI_H_ + +#define PEI_CAPSULE_PPI_GUID \ + { \ + 0x3acf33ee, 0xd892, 0x40f4, 0xa2, 0xfc, 0x38, 0x54, 0xd2, 0xe1, 0x32, 0x3d \ + } + +EFI_FORWARD_DECLARATION (PEI_CAPSULE_PPI); + +typedef +EFI_STATUS +(EFIAPI *PEI_CAPSULE_COALESCE) ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **MemoryBase, + IN OUT UINTN *MemSize + ); + +typedef +EFI_STATUS +(EFIAPI *PEI_CAPSULE_CREATE_STATE) ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *CapsuleBase, // returned from coalesce + IN UINTN CapsuleSize // returned from coalesce + ); + +typedef +EFI_STATUS +(EFIAPI *PEI_CAPSULE_CHECK_CAPSULE_UPDATE) ( + IN EFI_PEI_SERVICES **PeiServices + ); + +typedef struct _PEI_CAPSULE_PPI { + PEI_CAPSULE_COALESCE Coalesce; + PEI_CAPSULE_CHECK_CAPSULE_UPDATE CheckCapsuleUpdate; + PEI_CAPSULE_CREATE_STATE CreateState; +} PEI_CAPSULE_PPI; + +extern EFI_GUID gPeiCapsulePpiGuid; + +#endif // #ifndef _PEI_CAPSULE_PPI_H_ diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/PlatformMemoryRange.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/PlatformMemoryRange.h new file mode 100644 index 0000000000..b2faf4c7f6 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/PlatformMemoryRange.h @@ -0,0 +1,150 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PlatformMemoryRange.h + +Abstract: + + Platform Memory Range PPI as defined in EFI 2.0 + + PPI for reserving special purpose memory ranges. + +--*/ +// +// +#ifndef _PEI_PLATFORM_MEMORY_RANGE_H_ +#define _PEI_PLATFORM_MEMORY_RANGE_H_ + +#define PEI_PLATFORM_MEMORY_RANGE_PPI_GUID \ + { \ + 0x30eb2979, 0xb0f7, 0x4d60, 0xb2, 0xdc, 0x1a, 0x2c, 0x96, 0xce, 0xb1, 0xf4 \ + } + +typedef struct _PEI_PLATFORM_MEMORY_RANGE_PPI PEI_PLATFORM_MEMORY_RANGE_PPI ; + +#define PEI_MEMORY_RANGE_OPTION_ROM UINT32 + +#define PEI_MR_OPTION_ROM_ALL 0xFFFFFFFF +#define PEI_MR_OPTION_ROM_NONE 0x00000000 +#define PEI_MR_OPTION_ROM_C0000_16K 0x00000001 +#define PEI_MR_OPTION_ROM_C4000_16K 0x00000002 +#define PEI_MR_OPTION_ROM_C8000_16K 0x00000004 +#define PEI_MR_OPTION_ROM_CC000_16K 0x00000008 +#define PEI_MR_OPTION_ROM_D0000_16K 0x00000010 +#define PEI_MR_OPTION_ROM_D4000_16K 0x00000020 +#define PEI_MR_OPTION_ROM_D8000_16K 0x00000040 +#define PEI_MR_OPTION_ROM_DC000_16K 0x00000080 +#define PEI_MR_OPTION_ROM_E0000_16K 0x00000100 +#define PEI_MR_OPTION_ROM_E4000_16K 0x00000200 +#define PEI_MR_OPTION_ROM_E8000_16K 0x00000400 +#define PEI_MR_OPTION_ROM_EC000_16K 0x00000800 +#define PEI_MR_OPTION_ROM_F0000_16K 0x00001000 +#define PEI_MR_OPTION_ROM_F4000_16K 0x00002000 +#define PEI_MR_OPTION_ROM_F8000_16K 0x00004000 +#define PEI_MR_OPTION_ROM_FC000_16K 0x00008000 + +// +// 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 +// +// If adding additional entries, SMRAM Size +// is a multiple of 128KB. +// +#define PEI_MR_SMRAM_SIZE_MASK 0x0000FFFF +#define PEI_MR_SMRAM_SIZE_128K_MASK 0x00000001 +#define PEI_MR_SMRAM_SIZE_256K_MASK 0x00000002 +#define PEI_MR_SMRAM_SIZE_512K_MASK 0x00000004 +#define PEI_MR_SMRAM_SIZE_1024K_MASK 0x00000008 +#define PEI_MR_SMRAM_SIZE_2048K_MASK 0x00000010 +#define PEI_MR_SMRAM_SIZE_4096K_MASK 0x00000020 +#define PEI_MR_SMRAM_SIZE_8192K_MASK 0x00000040 + +#define PEI_MR_SMRAM_ABSEG_128K_NOCACHE 0x00010001 +#define PEI_MR_SMRAM_HSEG_128K_CACHE 0x80020001 +#define PEI_MR_SMRAM_HSEG_128K_NOCACHE 0x00020001 +#define PEI_MR_SMRAM_TSEG_128K_CACHE 0x80040001 +#define PEI_MR_SMRAM_TSEG_128K_NOCACHE 0x00040001 +#define PEI_MR_SMRAM_TSEG_256K_CACHE 0x80040002 +#define PEI_MR_SMRAM_TSEG_256K_NOCACHE 0x00040002 +#define PEI_MR_SMRAM_TSEG_512K_CACHE 0x80040004 +#define PEI_MR_SMRAM_TSEG_512K_NOCACHE 0x00040004 +#define PEI_MR_SMRAM_TSEG_1024K_CACHE 0x80040008 +#define PEI_MR_SMRAM_TSEG_1024K_NOCACHE 0x00040008 + +// +// Graphics Memory Range +// +#define PEI_MEMORY_RANGE_GRAPHICS_MEMORY UINT32 +#define PEI_MR_GRAPHICS_MEMORY_ALL 0xFFFFFFFF +#define PEI_MR_GRAPHICS_MEMORY_NONE 0x00000000 +#define PEI_MR_GRAPHICS_MEMORY_CACHEABLE 0x80000000 +// +// If adding additional entries, Graphics Memory Size +// is a multiple of 512KB. +// +#define PEI_MR_GRAPHICS_MEMORY_SIZE_MASK 0x0000FFFF +#define PEI_MR_GRAPHICS_MEMORY_512K_NOCACHE 0x00000001 +#define PEI_MR_GRAPHICS_MEMORY_512K_CACHE 0x80000001 +#define PEI_MR_GRAPHICS_MEMORY_1M_NOCACHE 0x00000002 +#define PEI_MR_GRAPHICS_MEMORY_1M_CACHE 0x80000002 +#define PEI_MR_GRAPHICS_MEMORY_4M_NOCACHE 0x00000008 +#define PEI_MR_GRAPHICS_MEMORY_4M_CACHE 0x80000008 +#define PEI_MR_GRAPHICS_MEMORY_8M_NOCACHE 0x00000010 +#define PEI_MR_GRAPHICS_MEMORY_8M_CACHE 0x80000010 +#define PEI_MR_GRAPHICS_MEMORY_16M_NOCACHE 0x00000020 +#define PEI_MR_GRAPHICS_MEMORY_16M_CACHE 0x80000020 +#define PEI_MR_GRAPHICS_MEMORY_32M_NOCACHE 0x00000040 +#define PEI_MR_GRAPHICS_MEMORY_32M_CACHE 0x80000040 +#define PEI_MR_GRAPHICS_MEMORY_48M_NOCACHE 0x00000060 +#define PEI_MR_GRAPHICS_MEMORY_48M_CACHE 0x80000060 +#define PEI_MR_GRAPHICS_MEMORY_64M_NOCACHE 0x00000080 +#define PEI_MR_GRAPHICS_MEMORY_64M_CACHE 0x80000080 +#define PEI_MR_GRAPHICS_MEMORY_128M_NOCACHE 0x00000100 +#define PEI_MR_GRAPHICS_MEMORY_128M_CACHE 0x80000100 +#define PEI_MR_GRAPHICS_MEMORY_256M_NOCACHE 0x00000200 +#define PEI_MR_GRAPHICS_MEMORY_256M_CACHE 0x80000200 +// +// Pci Memory Hole +// +#define PEI_MEMORY_RANGE_PCI_MEMORY UINT32 +#define PEI_MR_PCI_MEMORY_SIZE_512M_MASK 0x00000001 + +typedef +EFI_STATUS +(EFIAPI *PEI_CHOOSE_RANGES) ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_PLATFORM_MEMORY_RANGE_PPI * This, + IN OUT PEI_MEMORY_RANGE_OPTION_ROM * OptionRomMask, + IN OUT PEI_MEMORY_RANGE_SMRAM * SmramMask, + IN OUT PEI_MEMORY_RANGE_GRAPHICS_MEMORY * GraphicsMemoryMask, + IN OUT PEI_MEMORY_RANGE_PCI_MEMORY * PciMemoryMask + ); + +struct _PEI_PLATFORM_MEMORY_RANGE_PPI { + PEI_CHOOSE_RANGES ChooseRanges; +}; + +extern EFI_GUID gPeiPlatformMemoryRangePpiGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/PlatformMemorySize.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/PlatformMemorySize.h new file mode 100644 index 0000000000..6aa66b51cd --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/PlatformMemorySize.h @@ -0,0 +1,52 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + PlatformMemorySize.h + +Abstract: + + Platform Memory Size PPI as defined in Tiano + + PPI for describing the minimum platform memory size in order to successfully + pass control into DXE + +--*/ +// +// +#ifndef _PEI_PLATFORM_MEMORY_SIZE_H_ +#define _PEI_PLATFORM_MEMORY_SIZE_H_ + +#define PEI_PLATFORM_MEMORY_SIZE_PPI_GUID \ + { \ + 0x9a7ef41e, 0xc140, 0x4bd1, 0xb8, 0x84, 0x1e, 0x11, 0x24, 0xb, 0x4c, 0xe6 \ + } + +EFI_FORWARD_DECLARATION (PEI_PLATFORM_MEMORY_SIZE_PPI); + +typedef +EFI_STATUS +(EFIAPI *PEI_GET_MINIMUM_PLATFORM_MEMORY_SIZE) ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_PLATFORM_MEMORY_SIZE_PPI * This, + IN OUT UINT64 *MemorySize + ); + +typedef struct _PEI_PLATFORM_MEMORY_SIZE_PPI { + PEI_GET_MINIMUM_PLATFORM_MEMORY_SIZE GetPlatformMemorySize; +} PEI_PLATFORM_MEMORY_SIZE_PPI; + +extern EFI_GUID gPeiPlatformMemorySizePpiGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/SmmAccess.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/SmmAccess.h new file mode 100644 index 0000000000..674d566200 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/SmmAccess.h @@ -0,0 +1,171 @@ +// +// +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + SmmAccess.h + +Abstract: + + SmmAccess PPI + + This code abstracts the PEI core to provide SmmAccess services. + +--*/ + +#ifndef _PEI_SMM_ACCESS_PPI_H_ +#define _PEI_SMM_ACCESS_PPI_H_ + +#ifdef ECP_FLAG +#include "Guid/SmramMemoryReserve/SmramMemoryReserve.h" +#else +#include "Guid/SmramMemoryReserve.h" +#endif + +#define PEI_SMM_ACCESS_PPI_GUID \ + { \ + 0x268f33a9, 0xcccd, 0x48be, 0x88, 0x17, 0x86, 0x5, 0x3a, 0xc3, 0x2e, 0xd6 \ + } + +typedef struct _PEI_SMM_ACCESS_PPI PEI_SMM_ACCESS_PPI; + +typedef +EFI_STATUS +(EFIAPI *PEI_SMM_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. +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *PEI_SMM_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. 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 PEIM. + + 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. + +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *PEI_SMM_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. + +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *PEI_SMM_CAPABILITIES) ( + 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. +--*/ +; + +struct _PEI_SMM_ACCESS_PPI { + PEI_SMM_OPEN Open; + PEI_SMM_CLOSE Close; + PEI_SMM_LOCK Lock; + PEI_SMM_CAPABILITIES GetCapabilities; + BOOLEAN LockState; + BOOLEAN OpenState; +}; + +extern EFI_GUID gPeiSmmAccessPpiGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/VlvMmioPolicy.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/VlvMmioPolicy.h new file mode 100644 index 0000000000..53a5c12341 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/VlvMmioPolicy.h @@ -0,0 +1,45 @@ + +/*++ + +Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + VlvMmioPolicy.h + +Abstract: + + Interface definition details between ValleyView platform drivers during PEI phase. + +--*/ + +#ifndef _VLV_MMIO_POLICY_PPI_H_ +#define _VLV_MMIO_POLICY_PPI_H_ + +#define VLV_MMIO_POLICY_PPI_GUID \ + { \ + 0xE767BF7F, 0x4DB6, 0x5B34, 0x10, 0x11, 0x4F, 0xBE, 0x4C, 0xA7, 0xAF, 0xD2 \ + } + +extern EFI_GUID gVlvMmioPolicyPpiGuid; + + +// +// MRC Platform Policiy PPI +// +typedef struct _VLV_MMIO_POLICY_PPI { + UINT16 MmioSize; +} VLV_MMIO_POLICY_PPI; + +#pragma pack() + +#endif // _VLV_MMIO_POLICY_PPI_H_ diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/VlvPeiInit.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/VlvPeiInit.h new file mode 100644 index 0000000000..9ad30ccd73 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/VlvPeiInit.h @@ -0,0 +1,41 @@ + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + VlvPeiInit.h + +Abstract: + + Interface definition between ValleyView MRC and VlvInitPeim driver.. + +--*/ + +#ifndef _VLV_PEI_INIT_H_ +#define _VLV_PEI_INIT_H_ + +// +// Define the VLV PEI Init PPI GUID +// +#define VLV_PEI_INIT_PPI_GUID \ + { \ + 0x9ea8911, 0xbe0d, 0x4230, 0xa0, 0x3, 0xed, 0xc6, 0x93, 0xb4, 0x8e, 0x11 \ + } + +// +// Extern the GUID for PPI users. +// +extern EFI_GUID gVlvPeiInitPpiGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/VlvPolicy.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/VlvPolicy.h new file mode 100644 index 0000000000..19061f7ad2 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Ppi/VlvPolicy.h @@ -0,0 +1,112 @@ + +/*++ + +Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + VlvPolicy.h + +Abstract: + + Interface definition details between ValleyView MRC and platform drivers during PEI phase. + +--*/ + +#ifndef _VLV_POLICY_PPI_H_ +#define _VLV_POLICY_PPI_H_ + +// +// MRC Policy provided by platform for PEI phase {7D84B2C2-22A1-4372-B12C-EBB232D3A6A3} +// +#define VLV_POLICY_PPI_GUID \ + { \ + 0x7D84B2C2, 0x22A1, 0x4372, 0xB1, 0x2C, 0xEB, 0xB2, 0x32, 0xD3, 0xA6, 0xA3 \ + } + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gVlvPolicyPpiGuid; + +// +// PPI revision number +// Any backwards compatible changes to this PPI will result in an update in the revision number +// Major changes will require publication of a new PPI +// +#define MRC_PLATFORM_POLICY_PPI_REVISION 1 + +#ifndef MAX_SOCKETS +#define MAX_SOCKETS 4 +#endif + +#define S3_TIMING_DATA_LEN 9 +#define S3_READ_TRAINING_DATA_LEN 16 +#define S3_WRITE_TRAINING_DATA_LEN 12 + +#ifndef S3_RESTORE_DATA_LEN +#define S3_RESTORE_DATA_LEN (S3_TIMING_DATA_LEN + S3_READ_TRAINING_DATA_LEN + S3_WRITE_TRAINING_DATA_LEN) +#endif // S3_RESTORE_DATA_LEN +#pragma pack(1) +// +// MRC Platform Data Structure +// +typedef struct { + UINT8 SpdAddressTable[MAX_SOCKETS]; + UINT8 TSonDimmSmbusAddress[MAX_SOCKETS]; + + UINT16 SmbusBar; + UINT32 IchRcba; + UINT32 WdbBaseAddress; // Write Data Buffer area (WC caching mode) + UINT32 WdbRegionSize; + UINT32 SmBusAddress; + UINT8 UserBd; + UINT8 PlatformType; + UINT8 FastBoot; + UINT8 DynSR; +} VLV_PLATFORM_DATA; + + +typedef struct { + UINT16 MmioSize; + UINT16 GttSize; + UINT8 IgdDvmt50PreAlloc; + UINT8 PrimaryDisplay; + UINT8 PAVPMode; + UINT8 ApertureSize; + UINT8 InternalGraphics; + UINT8 IgdTurboEn; +} GT_CONFIGURATION; + +typedef struct { + UINT8 EccSupport; + UINT16 DdrFreqLimit; + UINT8 MaxTolud; +} MEMORY_CONFIGURATION; + + +// +// MRC Platform Policiy PPI +// +typedef struct _VLV_POLICY_PPI { + UINT8 Revision; + VLV_PLATFORM_DATA PlatformData; + GT_CONFIGURATION GtConfig; + MEMORY_CONFIGURATION MemConfig; + VOID *S3DataPtr; // was called MRC_PARAMS_SAVE_RESTORE + UINT8 ISPEn; //ISP (IUNIT) Device Enabled + UINT8 ISPPciDevConfig; //ISP (IUNIT) Device Config: 0->B0/D2/F0 for Window OS, 1->B0D3/F0 for Linux OS +} VLV_POLICY_PPI; + +#pragma pack() + +#endif // _VLV_POLICY_PPI_H_ diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/IgdOpRegion.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/IgdOpRegion.h new file mode 100644 index 0000000000..8aa7c7b54d --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/IgdOpRegion.h @@ -0,0 +1,219 @@ + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + IgdOpRegion.h + +Abstract: + + This file is part of the IGD OpRegion Implementation. The IGD OpRegion is + an interface between system BIOS, ASL code, and Graphics drivers. + + Supporting Specifiction: IGD OpRegion/Software SCI SPEC + + Note: Data structures defined in this protocol are packed not naturally + aligned. + + GUID forms: + {CDC5DDDF-E79D-41ec-A9B0-6565490DB9D3} + (0xcdc5dddf, 0xe79d, 0x41ec, 0xa9, 0xb0, 0x65, 0x65, 0x49, 0xd, 0xb9, 0xd3); + + Acronyms: + NVS: ACPI Non Volatile Storage + OpRegion: ACPI Operational Region + VBT: Video BIOS Table (OEM customizable data) + +--*/ + +#ifndef _IGD_OPREGION_PROTOCOL_H_ +#define _IGD_OPREGION_PROTOCOL_H_ + +// +// OpRegion / Software SCI protocol GUID +// +#define IGD_OPREGION_PROTOCOL_GUID \ + { \ + 0xcdc5dddf, 0xe79d, 0x41ec, 0xa9, 0xb0, 0x65, 0x65, 0x49, 0xd, 0xb9, 0xd3 \ + } + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gIgdOpRegionProtocolGuid; + +// +// Forward reference for pure ANSI compatability +// +typedef struct _IGD_OPREGION_PROTOCOL IGD_OPREGION_PROTOCOL; + +// +// Protocol data definitions +// + +// +// OpRegion structures: +// Sub-structures define the different parts of the OpRegion followed by the +// main structure representing the entire OpRegion. +// +// Note: These structures are packed to 1 byte offsets because the exact +// data location is requred by the supporting design specification due to +// the fact that the data is used by ASL and Graphics driver code compiled +// separatly. +// + +// +// OpRegion header (mailbox 0) structure and #defines. +// +#pragma pack (1) +typedef struct { + CHAR8 SIGN[0x10]; // 0 OpRegion signature + UINT32 SIZE; // 0x10 OpRegion size + UINT32 OVER; // 0x14 OpRegion structure version + UINT8 SVER[0x20]; // 0x18 System BIOS build version + UINT8 VVER[0x10]; // 0x38 Video BIOS build version + UINT8 GVER[0x10]; // 0x48 Graphic driver build version + UINT32 MBOX; // 0x58 Mailboxes supported + UINT32 DMOD; // 0x5C Driver Model + UINT32 PCON; // 0x60 Platform Configuration Info + CHAR8 GOPV[0x20]; // 0X64 GOP build version + UINT8 RSV[0x7C]; // Reserved +} OPREGION_HEADER; +#pragma pack () + +// +// OpRegion mailbox 1 (public ACPI Methods). +// +#pragma pack (1) +typedef struct { + UINT32 DRDY; // 0 Driver readiness + UINT32 CSTS; // 4 Status + UINT32 CEVT; // 8 Current event + UINT8 RM11[0x14]; // 12 Reserved + UINT32 DIDL; // 32 Supported display devices list + UINT32 DDL2; // 8 Devices. + UINT32 DDL3; + UINT32 DDL4; + UINT32 DDL5; + UINT32 DDL6; + UINT32 DDL7; + UINT32 DDL8; + UINT32 CPDL; // 64 Currently present display devices list + UINT32 CPL2; // 8 Devices. + UINT32 CPL3; + UINT32 CPL4; + UINT32 CPL5; + UINT32 CPL6; + UINT32 CPL7; + UINT32 CPL8; + UINT32 CADL; // 96 Currently active display devices list + UINT32 CAL2; // 8 Devices. + UINT32 CAL3; + UINT32 CAL4; + UINT32 CAL5; + UINT32 CAL6; + UINT32 CAL7; + UINT32 CAL8; + UINT32 NADL; // 128 Next active device list + UINT32 NDL2; // 8 Devices. + UINT32 NDL3; + UINT32 NDL4; + UINT32 NDL5; + UINT32 NDL6; + UINT32 NDL7; + UINT32 NDL8; + UINT32 ASLP; // 160 ASL sleep timeout + UINT32 TIDX; // 164 Toggle table index + UINT32 CHPD; // 168 Current hot plug enable indicator + UINT32 CLID; // 172 Current lid state indicator + UINT32 CDCK; // 176 Current docking state indicator + UINT32 SXSW; // 180 Display Switch notification on Sx State resume + UINT32 EVTS; // 184 Events supported by ASL + UINT32 CNOT; // 188 Current OS Notification + UINT32 NRDY; // 192 Reasons for DRDY = 0 + UINT8 RM12[0x3C]; // 196 Reserved +} OPREGION_MBOX1; +#pragma pack () + +// +// OpRegion mailbox 2 (Software SCI Interface). +// +#pragma pack (1) +typedef struct { + UINT32 SCIC; // 0 Software SCI function number parameters + UINT32 PARM; // 4 Software SCI additional parameters + UINT32 DSLP; // 8 Driver sleep timeout + UINT8 RM21[0xF4]; // 12 Reserved +} OPREGION_MBOX2; +#pragma pack () + +// +// OpRegion mailbox 3 (Power Conservation). +// +#pragma pack (1) +typedef struct { + UINT32 ARDY; // 0 Driver readiness + UINT32 ASLC; // 4 ASLE interrupt command / status + UINT32 TCHE; // 8 Technology enabled indicator + UINT32 ALSI; // 12 Current ALS illuminance reading + UINT32 BCLP; // 16 Backlight britness to set + UINT32 PFIT; // 20 Panel fitting Current State or Request + UINT32 CBLV; // 24 Brightness Current State + UINT16 BCLM[0x14]; // 28 Backlight Brightness Level Duty Cycle Mapping Table + UINT32 CPFM; // 68 Panel Fitting Current Mode + UINT32 EPFM; // 72 Enabled Panel Fitting Mode + UINT8 PLUT[0x4A]; // 76 Panel Look Up Table + UINT32 PFMB; // 150 PWM Frequency and Minimum Brightness + UINT32 CCDV; // 154 Color Correction Default Values + UINT32 PCFT; // 158 Power Conservation Features + UINT8 RM31[0x5E]; // 162 Reserved +} OPREGION_MBOX3; +#pragma pack () + +// +// OpRegion mailbox 4 (VBT). +// +#pragma pack (1) +typedef struct { + UINT8 GVD1[0x1800]; // 6K Reserved +} OPREGION_VBT; +#pragma pack () + +#pragma pack (1) +typedef struct { + UINT8 EDIDOVRD[0x400]; // 6K Edid overriding data +} OPREGION_MBOX5; +#pragma pack () +// +// Entire OpRegion +// +#pragma pack (1) +typedef struct { + OPREGION_HEADER Header; // OpRegion header + OPREGION_MBOX1 MBox1; // Mailbox 1: Public ACPI Methods + OPREGION_MBOX2 MBox2; // Mailbox 2: Software SCI Inteface + OPREGION_MBOX3 MBox3; // Mailbox 3: Power Conservation + OPREGION_VBT VBT; // VBT: Video BIOS Table (OEM customizable data) + OPREGION_MBOX5 MBox5; +} IGD_OPREGION_STRUC; +#pragma pack () + +// +// Protocol data structure definition +// +struct _IGD_OPREGION_PROTOCOL { + IGD_OPREGION_STRUC *OpRegion; +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/MemInfo.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/MemInfo.h new file mode 100644 index 0000000000..74e31d48b1 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/MemInfo.h @@ -0,0 +1,89 @@ + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + MemInfo.h + +Abstract: + + This protocol provides the memory information data, such as + total physical memory size, memory frequency, memory size + of each dimm and rank. + + This protocol is EFI compatible. + +--*/ + +#ifndef _MEM_INFO_PROTOCOL_H_ +#define _MEM_INFO_PROTOCOL_H_ + +// +// Define the protocol GUID +// +#define MEM_INFO_PROTOCOL_GUID \ + { \ + 0x6f20f7c8, 0xe5ef, 0x4f21, 0x8d, 0x19, 0xed, 0xc5, 0xf0, 0xc4, 0x96, 0xae \ + } + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gMemInfoProtocolGuid; + +// +// Forward reference for ANSI C compatibility +// +typedef struct _MEM_INFO_PROTOCOL MEM_INFO_PROTOCOL; + +// +// Protocol definitions +// + +#define CH_NUM 2 +#define DIMM_NUM 1 +#define RANK_NUM 2 + +#pragma pack(1) +typedef struct { + UINT32 memSize; + UINT8 ddrFreq; + UINT8 ddrType; + BOOLEAN EccSupport; + UINT16 dimmSize[CH_NUM * DIMM_NUM]; + UINT8 reserved; + UINT16 reserved2; +} MEMORY_INFO_DATA; +#pragma pack() + +/*++ +Data definition: + + memSize Total physical memory size + ddrFreq DDR Frequency + EccSupport ECC Support + dimmSize Dimm Size + DimmExist Dimm Present or not + RankInDimm No. of ranks in a dimm + +--*/ + +// +// Protocol definition +// +struct _MEM_INFO_PROTOCOL { + MEMORY_INFO_DATA MemInfoData; +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/PlatformGopPolicy.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/PlatformGopPolicy.h new file mode 100644 index 0000000000..7e948c70b1 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/PlatformGopPolicy.h @@ -0,0 +1,73 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +--*/ + +/** @file +**/ + +#ifndef _PLATFORM_GOP_POLICY_PROTOCOL_H_ +#define _PLATFORM_GOP_POLICY_PROTOCOL_H_ + +#define EFI_PLATFORM_GOP_POLICY_PROTOCOL_GUID \ + { 0xec2e931b, 0x3281, 0x48a5, 0x81, 0x7, 0xdf, 0x8a, 0x8b, 0xed, 0x3c, 0x5d } + +#define EFI_BMP_IMAGE_GUID \ + { 0x878AC2CC, 0x5343, 0x46F2, 0xB5, 0x63, 0x51, 0xF8, 0x9D, 0xAF, 0x56, 0xBA } + +#define PLATFORM_GOP_POLICY_PROTOCOL_REVISION_01 0x01 +#define PLATFORM_GOP_POLICY_PROTOCOL_REVISION_02 x0222 + +#pragma pack(1) + +typedef enum { + LidClosed, + LidOpen, + LidStatusMax +} LID_STATUS; + +typedef enum { + Docked, + UnDocked, + DockStatusMax +} DOCK_STATUS; + +typedef +EFI_STATUS +(EFIAPI *GET_PLATFORM_LID_STATUS) ( + OUT LID_STATUS *CurrentLidStatus + ); + +typedef +EFI_STATUS +(EFIAPI *GET_VBT_DATA) ( + OUT EFI_PHYSICAL_ADDRESS *VbtAddress, + OUT UINT32 *VbtSize + ); + +#pragma pack() + +typedef struct _PLATFORM_GOP_POLICY_PROTOCOL { + UINT32 Revision; + GET_PLATFORM_LID_STATUS GetPlatformLidStatus; + GET_VBT_DATA GetVbtData; +} PLATFORM_GOP_POLICY_PROTOCOL; + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gPlatformGOPPolicyGuid; + +extern EFI_GUID gBmpImageGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/VlvPlatformPolicy.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/VlvPlatformPolicy.h new file mode 100644 index 0000000000..de98c590f5 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Protocol/VlvPlatformPolicy.h @@ -0,0 +1,111 @@ + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + VlvPlatformPolicy.h + +Abstract: + + Interface definition details between MCH and platform drivers during DXE phase. + +--*/ + +#ifndef _VLV_PLATFORM_POLICY_H_ +#define _VLV_PLATFORM_POLICY_H_ + +// +// VLV Policy provided by platform for DXE phase {5BAB88BA-E0E2-4674-B6AD-B812F6881CD6} +// +#define DXE_VLV_PLATFORM_POLICY_GUID \ + {0x5bab88ba, 0xe0e2, 0x4674, 0xb6, 0xad, 0xb8, 0x12, 0xf6, 0x88, 0x1c, 0xd6} + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gDxeVlvPlatformPolicyGuid; + +// +// Protocol revision number +// Any backwards compatible changes to this protocol will result in an update in the revision number +// Major changes will require publication of a new protocol +// +#define DXE_VLV_PLATFORM_POLICY_PROTOCOL_REVISION 0 + + +typedef struct { + UINT8 PFITStatus; + UINT8 IgdTheramlSupport; + UINT8 ALSEnabled; + UINT8 LidStatus; +} IGD_PANEL_FEATURES; + +typedef struct { + UINT8 Reserved00; + UINT8 Reserved01; + UINT16 Reserved02; + UINT16 Reserved03; + UINT16 Reserved04; + UINT16 Reserved05; + UINT16 Reserved06; + UINT16 Reserved07; + UINT16 Reserved08; + UINT16 Reserved09; + UINT16 Reserved0A; + UINT16 Reserved0B; + UINT16 Reserved0C; + UINT16 Reserved0D; + UINT8 Reserved0E; + UINT8 Reserved0F; + UINT32 Reserved10; + UINT32 Reserved11; + UINT32 Reserved12; + UINT32 Reserved13; + UINT32 Reserved14; + UINT8 Reserved15; + UINT8 Reserved16; +} DPTF_SETTINGS; + +// +// MCH DXE Platform Policiy ================================================== +// + +#define NO_AUDIO 0 +#define HD_AUDIO 1 +#define LPE_AUDIO 2 + +typedef struct _DXE_VLV_PLATFORM_POLICY_PROTOCOL { + UINT8 Revision; + IGD_PANEL_FEATURES IgdPanelFeatures; + DPTF_SETTINGS Reserved; + UINT8 GraphicReserve00; + UINT8 GraphicsPerfAnalyzers; + UINT8 PwmReserved00; + UINT8 PwmReserved01; + UINT8 PmSupport; + UINT8 GraphicReserve01; + UINT8 GfxPause; + UINT8 GraphicsFreqReq; + UINT8 GraphicReserve03; + UINT8 GraphicReserve02; + UINT8 GraphicReserve04; + UINT8 PavpMode; + UINT8 GraphicReserve05; + UINT8 UlClockGating; + UINT8 IdleReserve; + UINT8 AudioTypeSupport; + UINT8 GraphicReserve06; +} DXE_VLV_PLATFORM_POLICY_PROTOCOL; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Valleyview.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Valleyview.h new file mode 100644 index 0000000000..ccb4eb3516 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/Valleyview.h @@ -0,0 +1,61 @@ + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Valleyview.h + +Abstract: + + This header file provides common definitions just for Valleyview-SOC using to avoid including extra module's file. +--*/ + +#ifndef _MC_H_INCLUDED_ +#define _MC_H_INCLUDED_ +/* +< Extended Configuration Base Address.*/ +#define EC_BASE 0xE0000000 + +// +// DEVICE 0 (Memroy Controller Hub) +// +#define MC_BUS 0x00 +#define MC_DEV 0x00 +#define MC_DEV2 0x02 +#define MC_FUN 0x00 +// NC DEV 0 Vendor and Device IDs +#define MC_VID 0x8086 +#define MC_DID_OFFSET 0x2 //Device Identification +#define MC_GGC_OFFSET 0x50 //GMCH Graphics Control Register + +// +// Device 2 Register Equates +// +#define IGD_BUS 0x00 +#define IGD_DEV 0x02 +#define IGD_FUN_0 0x00 +#define IGD_FUN_1 0x01 +#define IGD_DEV_FUN (IGD_DEV << 3) +#define IGD_BUS_DEV_FUN (MC_BUS << 8) + IGD_DEV_FUN +#define IGD_VID 0x8086 +#define IGD_DID 0xA001 +#define IGD_MGGC_OFFSET 0x0050 //GMCH Graphics Control Register 0x50 +#define IGD_BSM_OFFSET 0x005C //Base of Stolen Memory +#define IGD_SWSCI_OFFSET 0x00E0 //Software SCI 0xE0 2 +#define IGD_ASLE_OFFSET 0x00E4 //System Display Event Register 0xE4 4 +#define IGD_ASLS_OFFSET 0x00FC // ASL Storage +#define IGD_DID_QS 0x0BE2 //RCOverride -a: Fix the DID error + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/VlvAccess.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/VlvAccess.h new file mode 100644 index 0000000000..1a1326c976 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/VlvAccess.h @@ -0,0 +1,260 @@ + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + vlvAccess.h + +Abstract: + + Macros to simplify and abstract the interface to PCI configuration. + +--*/ + +#ifndef _VLVACCESS_H_INCLUDED_ +#define _VLVACCESS_H_INCLUDED_ + +#include "Valleyview.h" +#include "VlvCommonDefinitions.h" +#include + +// +// Memory Mapped IO access macros used by MSG BUS LIBRARY +// +#define MmioAddress( BaseAddr, Register ) \ + ( (UINTN)BaseAddr + \ + (UINTN)(Register) \ + ) + + +// +// UINT32 +// + +#define Mmio32Ptr( BaseAddr, Register ) \ + ( (volatile UINT32 *)MmioAddress( BaseAddr, Register ) ) + +#define Mmio32( BaseAddr, Register ) \ + *Mmio32Ptr( BaseAddr, Register ) + +#define Mmio32Or( BaseAddr, Register, OrData ) \ + Mmio32( BaseAddr, Register ) = \ + (UINT32) ( \ + Mmio32( BaseAddr, Register ) | \ + (UINT32)(OrData) \ + ) + +#define Mmio32And( BaseAddr, Register, AndData ) \ + Mmio32( BaseAddr, Register ) = \ + (UINT32) ( \ + Mmio32( BaseAddr, Register ) & \ + (UINT32)(AndData) \ + ) + +#define Mmio32AndThenOr( BaseAddr, Register, AndData, OrData ) \ + Mmio32( BaseAddr, Register ) = \ + (UINT32) ( \ + ( Mmio32( BaseAddr, Register ) & \ + (UINT32)(AndData) \ + ) | \ + (UINT32)(OrData) \ + ) + +// +// UINT16 +// + +#define Mmio16Ptr( BaseAddr, Register ) \ + ( (volatile UINT16 *)MmioAddress( BaseAddr, Register ) ) + +#define Mmio16( BaseAddr, Register ) \ + *Mmio16Ptr( BaseAddr, Register ) + +#define Mmio16Or( BaseAddr, Register, OrData ) \ + Mmio16( BaseAddr, Register ) = \ + (UINT16) ( \ + Mmio16( BaseAddr, Register ) | \ + (UINT16)(OrData) \ + ) + +#define Mmio16And( BaseAddr, Register, AndData ) \ + Mmio16( BaseAddr, Register ) = \ + (UINT16) ( \ + Mmio16( BaseAddr, Register ) & \ + (UINT16)(AndData) \ + ) + +#define Mmio16AndThenOr( BaseAddr, Register, AndData, OrData ) \ + Mmio16( BaseAddr, Register ) = \ + (UINT16) ( \ + ( Mmio16( BaseAddr, Register ) & \ + (UINT16)(AndData) \ + ) | \ + (UINT16)(OrData) \ + ) + +// +// UINT8 +// + +#define Mmio8Ptr( BaseAddr, Register ) \ + ( (volatile UINT8 *)MmioAddress( BaseAddr, Register ) ) + +#define Mmio8( BaseAddr, Register ) \ + *Mmio8Ptr( BaseAddr, Register ) + +#define Mmio8Or( BaseAddr, Register, OrData ) \ + Mmio8( BaseAddr, Register ) = \ + (UINT8) ( \ + Mmio8( BaseAddr, Register ) | \ + (UINT8)(OrData) \ + ) + +#define Mmio8And( BaseAddr, Register, AndData ) \ + Mmio8( BaseAddr, Register ) = \ + (UINT8) ( \ + Mmio8( BaseAddr, Register ) & \ + (UINT8)(AndData) \ + ) + +#define Mmio8AndThenOr( BaseAddr, Register, AndData, OrData ) \ + Mmio8( BaseAddr, Register ) = \ + (UINT8) ( \ + ( Mmio8( BaseAddr, Register ) & \ + (UINT8)(AndData) \ + ) | \ + (UINT8)(OrData) \ + ) + +// +// MSG BUS API +// + +#define MSG_BUS_ENABLED 0x000000F0 +#define MSGBUS_MASKHI 0xFFFFFF00 +#define MSGBUS_MASKLO 0x000000FF + +#define MESSAGE_BYTE_EN BIT4 +#define MESSAGE_WORD_EN BIT4 | BIT5 +#define MESSAGE_DWORD_EN BIT4 | BIT5 | BIT6 | BIT7 + +#define SIDEBAND_OPCODE 0x78 +#define MEMREAD_OPCODE 0x00000000 +#define MEMWRITE_OPCODE 0x01000000 + + + +/***************************/ +// +// Memory mapped PCI IO +// + +#define PciCfgPtr(Bus, Device, Function, Register )\ + (UINTN)(Bus << 20) + \ + (UINTN)(Device << 15) + \ + (UINTN)(Function << 12) + \ + (UINTN)(Register) + +#define PciCfg32Read_CF8CFC(B,D,F,R) \ + (UINT32)(IoOut32(0xCF8,(0x80000000|(B<<16)|(D<<11)|(F<<8)|(R))),IoIn32(0xCFC)) + +#define PciCfg32Write_CF8CFC(B,D,F,R,Data) \ + (IoOut32(0xCF8,(0x80000000|(B<<16)|(D<<11)|(F<<8)|(R))),IoOut32(0xCFC,Data)) + +#define PciCfg32Or_CF8CFC(B,D,F,R,O) \ + PciCfg32Write_CF8CFC(B,D,F,R, \ + (PciCfg32Read_CF8CFC(B,D,F,R) | (O))) + +#define PciCfg32And_CF8CFC(B,D,F,R,A) \ + PciCfg32Write_CF8CFC(B,D,F,R, \ + (PciCfg32Read_CF8CFC(B,D,F,R) & (A))) + +#define PciCfg32AndThenOr_CF8CFC(B,D,F,R,A,O) \ + PciCfg32Write_CF8CFC(B,D,F,R, \ + (PciCfg32Read_CF8CFC(B,D,F,R) & (A)) | (O)) + +// +// Device 0, Function 0 +// +#define McD0PciCfg64(Register) MmPci64 (0, MC_BUS, 0, 0, Register) +#define McD0PciCfg64Or(Register, OrData) MmPci64Or (0, MC_BUS, 0, 0, Register, OrData) +#define McD0PciCfg64And(Register, AndData) MmPci64And (0, MC_BUS, 0, 0, Register, AndData) +#define McD0PciCfg64AndThenOr(Register, AndData, OrData) MmPci64AndThenOr (0, MC_BUS, 0, 0, Register, AndData, OrData) + +#define McD0PciCfg32(Register) MmPci32 (0, MC_BUS, 0, 0, Register) +#define McD0PciCfg32Or(Register, OrData) MmPci32Or (0, MC_BUS, 0, 0, Register, OrData) +#define McD0PciCfg32And(Register, AndData) MmPci32And (0, MC_BUS, 0, 0, Register, AndData) +#define McD0PciCfg32AndThenOr(Register, AndData, OrData) MmPci32AndThenOr (0, MC_BUS, 0, 0, Register, AndData, OrData) + +#define McD0PciCfg16(Register) MmPci16 (0, MC_BUS, 0, 0, Register) +#define McD0PciCfg16Or(Register, OrData) MmPci16Or (0, MC_BUS, 0, 0, Register, OrData) +#define McD0PciCfg16And(Register, AndData) MmPci16And (0, MC_BUS, 0, 0, Register, AndData) +#define McD0PciCfg16AndThenOr(Register, AndData, OrData) MmPci16AndThenOr (0, MC_BUS, 0, 0, Register, AndData, OrData) + +#define McD0PciCfg8(Register) MmPci8 (0, MC_BUS, 0, 0, Register) +#define McD0PciCfg8Or(Register, OrData) MmPci8Or (0, MC_BUS, 0, 0, Register, OrData) +#define McD0PciCfg8And(Register, AndData) MmPci8And (0, MC_BUS, 0, 0, Register, AndData) +#define McD0PciCfg8AndThenOr( Register, AndData, OrData ) MmPci8AndThenOr (0, MC_BUS, 0, 0, Register, AndData, OrData) + + +// +// Device 2, Function 0 +// +#define McD2PciCfg64(Register) MmPci64 (0, MC_BUS, 2, 0, Register) +#define McD2PciCfg64Or(Register, OrData) MmPci64Or (0, MC_BUS, 2, 0, Register, OrData) +#define McD2PciCfg64And(Register, AndData) MmPci64And (0, MC_BUS, 2, 0, Register, AndData) +#define McD2PciCfg64AndThenOr(Register, AndData, OrData) MmPci64AndThenOr (0, MC_BUS, 2, 0, Register, AndData, OrData) + +#define McD2PciCfg32(Register) MmPci32 (0, MC_BUS, 2, 0, Register) +#define McD2PciCfg32Or(Register, OrData) MmPci32Or (0, MC_BUS, 2, 0, Register, OrData) +#define McD2PciCfg32And(Register, AndData) MmPci32And (0, MC_BUS, 2, 0, Register, AndData) +#define McD2PciCfg32AndThenOr(Register, AndData, OrData) MmPci32AndThenOr (0, MC_BUS, 2, 0, Register, AndData, OrData) + +#define McD2PciCfg16(Register) MmPci16 (0, MC_BUS, 2, 0, Register) +#define McD2PciCfg16Or(Register, OrData) MmPci16Or (0, MC_BUS, 2, 0, Register, OrData) +#define McD2PciCfg16And(Register, AndData) MmPci16And (0, MC_BUS, 2, 0, Register, AndData) +#define McD2PciCfg16AndThenOr(Register, AndData, OrData) MmPci16AndThenOr (0, MC_BUS, 2, 0, Register, AndData, OrData) + +#define McD2PciCfg8(Register) MmPci8 (0, MC_BUS, 2, 0, Register) +#define McD2PciCfg8Or(Register, OrData) MmPci8Or (0, MC_BUS, 2, 0, Register, OrData) +#define McD2PciCfg8And(Register, AndData) MmPci8And (0, MC_BUS, 2, 0, Register, AndData) + +// +// IO +// + +#ifndef IoIn8 + +#define IoIn8(Port) \ + IoRead8(Port) + +#define IoIn16(Port) \ + IoRead16(Port) + +#define IoIn32(Port) \ + IoRead32(Port) + +#define IoOut8(Port, Data) \ + IoWrite8(Port, Data) + +#define IoOut16(Port, Data) \ + IoWrite16(Port, Data) + +#define IoOut32(Port, Data) \ + IoWrite32(Port, Data) + +#endif + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/VlvCommonDefinitions.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/VlvCommonDefinitions.h new file mode 100644 index 0000000000..3203fc6ea0 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/NorthCluster/Include/VlvCommonDefinitions.h @@ -0,0 +1,258 @@ + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + VlvCommonDefinitions.h + +Abstract: + + Macros to simplify and abstract the interface to PCI configuration. + +--*/ + +/// +/// 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 + +#ifndef _PCIACCESS_H_INCLUDED_ +#define _PCIACCESS_H_INCLUDED_ +#ifndef PCI_EXPRESS_BASE_ADDRESS + #define PCI_EXPRESS_BASE_ADDRESS 0xE0000000 +#endif + +#ifndef MmPciAddress +#define MmPciAddress( Segment, Bus, Device, Function, Register ) \ + ( (UINTN)PCI_EXPRESS_BASE_ADDRESS + \ + (UINTN)(Bus << 20) + \ + (UINTN)(Device << 15) + \ + (UINTN)(Function << 12) + \ + (UINTN)(Register) \ + ) +#endif + +// +// UINT64 +// +#define MmPci64Ptr( Segment, Bus, Device, Function, Register ) \ + ( (volatile UINT64 *)MmPciAddress( Segment, Bus, Device, Function, Register ) ) + +#define MmPci64( Segment, Bus, Device, Function, Register ) \ + *MmPci64Ptr( Segment, Bus, Device, Function, Register ) + +#define MmPci64Or( Segment, Bus, Device, Function, Register, OrData ) \ + MmPci64( Segment, Bus, Device, Function, Register ) = \ + (UINT64) ( \ + MmPci64( Segment, Bus, Device, Function, Register ) | \ + (UINT64)(OrData) \ + ) + +#define MmPci64And( Segment, Bus, Device, Function, Register, AndData ) \ + MmPci64( Segment, Bus, Device, Function, Register ) = \ + (UINT64) ( \ + MmPci64( Segment, Bus, Device, Function, Register ) & \ + (UINT64)(AndData) \ + ) + +#define MmPci64AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \ + MmPci64( Segment, Bus, Device, Function, Register ) = \ + (UINT64) ( \ + ( MmPci64( Segment, Bus, Device, Function, Register ) & \ + (UINT64)(AndData) \ + ) | \ + (UINT64)(OrData) \ + ) + +// +// UINT32 +// + +#define MmPci32Ptr( Segment, Bus, Device, Function, Register ) \ + ( (volatile UINT32 *) MmPciAddress( Segment, Bus, Device, Function, Register ) ) + +#define MmPci32( Segment, Bus, Device, Function, Register ) \ + *MmPci32Ptr( Segment, Bus, Device, Function, Register ) + +#define MmPci32Or( Segment, Bus, Device, Function, Register, OrData ) \ + MmPci32( Segment, Bus, Device, Function, Register ) = \ + (UINT32) ( \ + MmPci32( Segment, Bus, Device, Function, Register ) | \ + (UINT32)(OrData) \ + ) + +#define MmPci32And( Segment, Bus, Device, Function, Register, AndData ) \ + MmPci32( Segment, Bus, Device, Function, Register ) = \ + (UINT32) ( \ + MmPci32( Segment, Bus, Device, Function, Register ) & \ + (UINT32)(AndData) \ + ) + +#define MmPci32AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \ + MmPci32( Segment, Bus, Device, Function, Register ) = \ + (UINT32) ( \ + ( MmPci32( Segment, Bus, Device, Function, Register ) & \ + (UINT32)(AndData) \ + ) | \ + (UINT32)(OrData) \ + ) + +// +// UINT16 +// + +#define MmPci16Ptr( Segment, Bus, Device, Function, Register ) \ + ( (volatile UINT16 *)MmPciAddress( Segment, Bus, Device, Function, Register ) ) + +#define MmPci16( Segment, Bus, Device, Function, Register ) \ + *MmPci16Ptr( Segment, Bus, Device, Function, Register ) + +#define MmPci16Or( Segment, Bus, Device, Function, Register, OrData ) \ + MmPci16( Segment, Bus, Device, Function, Register ) = \ + (UINT16) ( \ + MmPci16( Segment, Bus, Device, Function, Register ) | \ + (UINT16)(OrData) \ + ) + +#define MmPci16And( Segment, Bus, Device, Function, Register, AndData ) \ + MmPci16( Segment, Bus, Device, Function, Register ) = \ + (UINT16) ( \ + MmPci16( Segment, Bus, Device, Function, Register ) & \ + (UINT16)(AndData) \ + ) + +#define MmPci16AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \ + MmPci16( Segment, Bus, Device, Function, Register ) = \ + (UINT16) ( \ + ( MmPci16( Segment, Bus, Device, Function, Register ) & \ + (UINT16)(AndData) \ + ) | \ + (UINT16)(OrData) \ + ) + +// +// UINT8 +// + +#define MmPci8Ptr( Segment, Bus, Device, Function, Register ) \ + ( (volatile UINT8 *)MmPciAddress( Segment, Bus, Device, Function, Register ) ) + +#define MmPci8( Segment, Bus, Device, Function, Register ) \ + *MmPci8Ptr( Segment, Bus, Device, Function, Register ) + +#define MmPci8Or( Segment, Bus, Device, Function, Register, OrData ) \ + MmPci8( Segment, Bus, Device, Function, Register ) = \ + (UINT8) ( \ + MmPci8( Segment, Bus, Device, Function, Register ) | \ + (UINT8)(OrData) \ + ) + +#define MmPci8And( Segment, Bus, Device, Function, Register, AndData ) \ + MmPci8( Segment, Bus, Device, Function, Register ) = \ + (UINT8) ( \ + MmPci8( Segment, Bus, Device, Function, Register ) & \ + (UINT8)(AndData) \ + ) + +#define MmPci8AndThenOr( Segment, Bus, Device, Function, Register, AndData, OrData ) \ + MmPci8( Segment, Bus, Device, Function, Register ) = \ + (UINT8) ( \ + ( MmPci8( Segment, Bus, Device, Function, Register ) & \ + (UINT8)(AndData) \ + ) | \ + (UINT8)(OrData) \ + ) + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/PchInitVar.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/PchInitVar.h new file mode 100644 index 0000000000..e6d232103b --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/PchInitVar.h @@ -0,0 +1,54 @@ +/*++ + +Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PchInitVar.h + +Abstract: + + This file defines variable shared between PCH Init DXE driver and PCH + Init S3 Resume PEIM. + +--*/ +#ifndef _PCH_INIT_VAR_H_ +#define _PCH_INIT_VAR_H_ + +#include +// +// Define the PCH Init Var GUID +// +#define PCH_INIT_VARIABLE_GUID {0xe6c2f70a, 0xb604, 0x4877,{0x85, 0xba, 0xde, 0xec, 0x89, 0xe1, 0x17, 0xeb}} +// +// Extern the GUID for PPI users. +// +extern EFI_GUID gPchInitVariableGuid; + +#define PCH_INIT_VARIABLE_NAME L"PchInit" + +// +// Define the Pch Init Variable structure +// +typedef struct { + UINT32 StorePosition; + UINT32 ExecutePosition; +} PCH_S3_PARAMETER_HEADER; + +#pragma pack(1) +typedef struct _PCH_INIT_VARIABLE { + PCH_S3_PARAMETER_HEADER *PchS3Parameter; +} PCH_INIT_VARIABLE; +#pragma pack() + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/SataControllerGuid.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/SataControllerGuid.h new file mode 100644 index 0000000000..52ce58e303 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/SataControllerGuid.h @@ -0,0 +1,40 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + SataControllerGuid.h + +Abstract: + + GUID for use in describing SataController + +--*/ +#ifndef _SERIAL_ATA_CONTROLLER_GUID_H_ +#define _SERIAL_ATA_CONTROLLER_GUID_H_ + +#ifdef ECP_FLAG +#define PCH_SATA_CONTROLLER_DRIVER_GUID \ + { \ + 0xbb929da9, 0x68f7, 0x4035, 0xb2, 0x2c, 0xa3, 0xbb, 0x3f, 0x23, 0xda, 0x55 \ + } +#else +#define PCH_SATA_CONTROLLER_DRIVER_GUID \ + {\ + 0xbb929da9, 0x68f7, 0x4035, 0xb2, 0x2c, 0xa3, 0xbb, 0x3f, 0x23, 0xda, 0x55 \} + +#endif + +extern EFI_GUID gSataControllerDriverGuid; +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/SmbusArpMap.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/SmbusArpMap.h new file mode 100644 index 0000000000..4e69679a32 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/SmbusArpMap.h @@ -0,0 +1,36 @@ +// +// +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + SmbusArpMap.h + +Abstract: + + GUID for use in describing SMBus devices that were ARPed during PEI. + +--*/ +#ifndef _EFI_SMBUS_ARP_MAP_GUID_H_ +#define _EFI_SMBUS_ARP_MAP_GUID_H_ + +#define EFI_SMBUS_ARP_MAP_GUID \ + { \ + 0x707be83e, 0x0bf6, 0x40a5, 0xbe, 0x64, 0x34, 0xc0, 0x3a, 0xa0, 0xb8, 0xe2 \ + } + +extern EFI_GUID gEfiSmbusArpMapGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/Vlv2Variable.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/Vlv2Variable.h new file mode 100644 index 0000000000..64d91f0e30 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Guid/Vlv2Variable.h @@ -0,0 +1,34 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Vlv2Variable.h + +Abstract: + + GUID used to define ValleyView2 variable. + +--*/ + +#ifndef _VLV2_VARIABLE_GUID_H_ +#define _VLV2_VARIABLE_GUID_H_ + +#define EFI_VLV2_VARIABLE \ + { \ + 0x10ba6bbe, 0xa97e, 0x41c3, {0x9a, 0x07, 0x60, 0x7a, 0xd9, 0xbd, 0x60, 0xe5 } \ + } +extern EFI_GUID gEfiVlv2VariableGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/IndustryStandard/CeAta.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/IndustryStandard/CeAta.h new file mode 100644 index 0000000000..b641ccb42a --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/IndustryStandard/CeAta.h @@ -0,0 +1,132 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +--*/ + + +/*++ + +Module Name: + + CEATA.h + +Abstract: + + Header file for chipset CE-AT spec. + +--*/ + +#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/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/IndustryStandard/Mmc.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/IndustryStandard/Mmc.h new file mode 100644 index 0000000000..2d5427ade9 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/IndustryStandard/Mmc.h @@ -0,0 +1,355 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +--*/ + + +/*++ + +Module Name: + + MMC.h + +Abstract: + + Header file for Industry MMC 4.2 spec. + +--*/ + +#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 B_PERM_WP_DIS 0x10 +#define B_PWR_WP_EN 0x01 +#define US_PERM_WP_DIS 0x10 +#define US_PWR_WP_EN 0x01 + +#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 Reserved133_0[134]; // [133:0] 0 + UINT8 SEC_BAD_BLOCK_MGMNT; // [134] Bad Block Management mode + UINT8 Reserved135; // [135] 0 + UINT8 ENH_START_ADDR[4]; // [139:136] Enhanced User Data Start Address + UINT8 ENH_SIZE_MULT[3]; // [142:140] Enhanced User Data Start Size + UINT8 GP_SIZE_MULT_1[3]; // [145:143] GPP1 Size + UINT8 GP_SIZE_MULT_2[3]; // [148:146] GPP2 Size + UINT8 GP_SIZE_MULT_3[3]; // [151:149] GPP3 Size + UINT8 GP_SIZE_MULT_4[3]; // [154:152] GPP4 Size + UINT8 PARTITION_SETTING_COMPLETED; // [155] Partitioning Setting + UINT8 PARTITIONS_ATTRIBUTES; // [156] Partitions attributes + UINT8 MAX_ENH_SIZE_MULT[3]; // [159:157] GPP4 Start Size + UINT8 PARTITIONING_SUPPORT; // [160] Partitioning Support + UINT8 HPI_MGMT; // [161] HPI management + UINT8 RST_n_FUNCTION; // [162] H/W reset function + UINT8 BKOPS_EN; // [163] Enable background operations handshake + UINT8 BKOPS_START; // [164] Manually start background operations + UINT8 Reserved165; // [165] 0 + UINT8 WR_REL_PARAM; // [166] Write reliability parameter register + UINT8 WR_REL_SET; // [167] Write reliability setting register + UINT8 RPMB_SIZE_MULT; // [168] RPMB Size + UINT8 FW_CONFIG; // [169] FW configuration + UINT8 Reserved170; // [170] 0 + UINT8 USER_WP; // [171] User area write protection + UINT8 Reserved172; // [172] 0 + UINT8 BOOT_WP; // [173] Boot area write protection + UINT8 Reserved174; // [174] 0 + UINT8 ERASE_GROUP_DEF; // [175] High density erase group definition + UINT8 Reserved176; // [176] 0 + UINT8 BOOT_BUS_WIDTH; // [177] Boot bus width + UINT8 BOOT_CONFIG_PROT; // [178] Boot config protection + UINT8 PARTITION_CONFIG; // [179] Partition config + UINT8 Reserved180; // [180] 0 + UINT8 ERASED_MEM_CONT; // [181] Erased Memory Content + UINT8 Reserved182; // [182] 0 + UINT8 BUS_WIDTH; // [183] Bus Width Mode + UINT8 Reserved184; // [184] 0 + UINT8 HS_TIMING; // [185] High Speed Interface Timing + UINT8 Reserved186; // [186] 0 + UINT8 POWER_CLASS; // [187] Power Class + UINT8 Reserved188; // [188] 0 + UINT8 CMD_SET_REV; // [189] Command Set Revision + UINT8 Reserved190; // [190] 0 + UINT8 CMD_SET; // [191] Command Set + UINT8 EXT_CSD_REV; // [192] Extended CSD Revision + UINT8 Reserved193; // [193] 0 + UINT8 CSD_STRUCTURE; // [194] CSD Structure Version + UINT8 Reserved195; // [195] 0 + UINT8 CARD_TYPE; // [196] Card Type + UINT8 Reserved197; // [197] 0 + UINT8 OUT_OF_INTERRUPT_TIME; // [198] Out-of-interrupt busy timing + UINT8 PARTITION_SWITCH_TIME; // [199] Partition switching timing + UINT8 PWR_CL_52_195; // [200] Power Class for 52MHz @ 1.95V + UINT8 PWR_CL_26_195; // [201] Power Class for 26MHz @ 1.95V + UINT8 PWR_CL_52_360; // [202] Power Class for 52MHz @ 3.6V + UINT8 PWR_CL_26_360; // [203] Power Class for 26MHz @ 3.6V + UINT8 Reserved204; // [204] 0 + UINT8 MIN_PERF_R_4_26; // [205] Minimum Read Performance for 4bit @26MHz + UINT8 MIN_PERF_W_4_26; // [206] Minimum Write Performance for 4bit @26MHz + UINT8 MIN_PERF_R_8_26_4_52; // [207] Minimum Read Performance for 8bit @26MHz/4bit @52MHz + UINT8 MIN_PERF_W_8_26_4_52; // [208] Minimum Write Performance for 8bit @26MHz/4bit @52MHz + UINT8 MIN_PERF_R_8_52; // [209] Minimum Read Performance for 8bit @52MHz + UINT8 MIN_PERF_W_8_52; // [210] Minimum Write Performance for 8bit @52MHz + UINT8 Reserved211; // [211] 0 + UINT8 SEC_COUNT[4]; // [215:212] Sector Count + UINT8 Reserved216; // [216] 0 + UINT8 S_A_TIMEOUT; // [217] Sleep/awake timeout + UINT8 Reserved218; // [218] 0 + UINT8 S_C_VCCQ; // [219] Sleep current (VCCQ) + UINT8 S_C_VCC; // [220] Sleep current (VCC) + UINT8 HC_WP_GRP_SIZE; // [221] High-capacity write protect group size + UINT8 REL_WR_SEC_C; // [222] Reliable write sector count + UINT8 ERASE_TIMEOUT_MULT; // [223] High-capacity erase timeout + UINT8 HC_ERASE_GRP_SIZE; // [224] High-capacity erase unit size + UINT8 ACC_SIZE; // [225] Access size + UINT8 BOOT_SIZE_MULTI; // [226] Boot partition size + UINT8 Reserved227; // [227] 0 + UINT8 BOOT_INFO; // [228] Boot information + UINT8 SEC_TRIM_MULT; // [229] Secure TRIM Multiplier + UINT8 SEC_ERASE_MULT; // [230] Secure Erase Multiplier + UINT8 SEC_FEATURE_SUPPORT; // [231] Secure Feature support + UINT8 TRIM_MULT; // [232] TRIM Multiplier + UINT8 Reserved233; // [233] 0 + UINT8 MIN_PERF_DDR_R_8_52; // [234] Min Read Performance for 8-bit @ 52MHz + UINT8 MIN_PERF_DDR_W_8_52; // [235] Min Write Performance for 8-bit @ 52MHz + UINT8 Reserved237_236[2]; // [237:236] 0 + UINT8 PWR_CL_DDR_52_195; // [238] Power class for 52MHz, DDR at 1.95V + UINT8 PWR_CL_DDR_52_360; // [239] Power class for 52MHz, DDR at 3.6V + UINT8 Reserved240; // [240] 0 + UINT8 INI_TIMEOUT_AP; // [241] 1st initialization time after partitioning + UINT8 CORRECTLY_PRG_SECTORS_NUM[4]; // [245:242] Number of correctly programmed sectors + UINT8 BKOPS_STATUS; // [246] Background operations status + UINT8 Reserved501_247[255]; // [501:247] 0 + UINT8 BKOPS_SUPPORT; // [502] Background operations support + UINT8 HPI_FEATURES; // [503] HPI features + UINT8 S_CMD_SET; // [504] Sector Count + UINT8 Reserved511_505[7]; // [511:505] Sector Count +} 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/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/IndustryStandard/SdCard.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/IndustryStandard/SdCard.h new file mode 100644 index 0000000000..835800d782 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/IndustryStandard/SdCard.h @@ -0,0 +1,163 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +--*/ + + +/*++ +Module Name: + + SDCard.h + +Abstract: + + Header file for Industry SD Card 2.0 spec. + +--*/ + +#ifndef _SD_CARD_H +#define _SD_CARD_H + +#include "Mmc.h" + +#pragma pack(1) + +#define CHECK_PATTERN 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/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Library/I2CLib.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Library/I2CLib.h new file mode 100644 index 0000000000..9173364c48 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Library/I2CLib.h @@ -0,0 +1,175 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + I2CRegs.h + +Abstract: + + Register Definitions for I2C Driver/PEIM. + +--*/ +#include +#include + +#ifndef I2C_REGS_A0_H +#define I2C_REGS_A0_H + +// +// FIFO write workaround value. +// +#define FIFO_WRITE_DELAY 2 + +// +// MMIO Register Definitions +// +#define R_IC_CON ( 0x00) // I2C Control +#define B_IC_RESTART_EN BIT5 +#define B_IC_SLAVE_DISABLE BIT6 +#define V_SPEED_STANDARD 0x02 +#define V_SPEED_FAST 0x04 +#define V_SPEED_HIGH 0x06 +#define B_MASTER_MODE BIT0 + +#define R_IC_TAR ( 0x04) // I2C Target Address +#define IC_TAR_10BITADDR_MASTER BIT12 + +#define R_IC_SAR ( 0x08) // I2C Slave Address +#define R_IC_HS_MADDR ( 0x0C) // I2C HS MasterMode Code Address +#define R_IC_DATA_CMD ( 0x10) // I2C Rx/Tx Data Buffer and Command + +#define B_READ_CMD BIT8 // 1 = read, 0 = write +#define B_CMD_STOP BIT9 // 1 = STOP +#define B_CMD_RESTART BIT10 // 1 = IC_RESTART_EN + +#define V_WRITE_CMD_MASK ( 0xFF) + +#define R_IC_SS_SCL_HCNT ( 0x14) // Standard Speed I2C Clock SCL High Count +#define R_IC_SS_SCL_LCNT ( 0x18) // Standard Speed I2C Clock SCL Low Count +#define R_IC_FS_SCL_HCNT ( 0x1C) // Full Speed I2C Clock SCL High Count +#define R_IC_FS_SCL_LCNT ( 0x20) // Full Speed I2C Clock SCL Low Count +#define R_IC_HS_SCL_HCNT ( 0x24) // High Speed I2C Clock SCL High Count +#define R_IC_HS_SCL_LCNT ( 0x28) // High Speed I2C Clock SCL Low Count +#define R_IC_INTR_STAT ( 0x2C) // I2C Inetrrupt Status +#define R_IC_INTR_MASK ( 0x30) // I2C Interrupt Mask +#define I2C_INTR_GEN_CALL BIT11 // General call received +#define I2C_INTR_START_DET BIT10 +#define I2C_INTR_STOP_DET BIT9 +#define I2C_INTR_ACTIVITY BIT8 +#define I2C_INTR_TX_ABRT BIT6 // Set on NACK +#define I2C_INTR_TX_EMPTY BIT4 +#define I2C_INTR_TX_OVER BIT3 +#define I2C_INTR_RX_FULL BIT2 // Data bytes in RX FIFO over threshold +#define I2C_INTR_RX_OVER BIT1 +#define I2C_INTR_RX_UNDER BIT0 +#define R_IC_RAW_INTR_STAT ( 0x34) // I2C Raw Interrupt Status +#define R_IC_RX_TL ( 0x38) // I2C Receive FIFO Threshold +#define R_IC_TX_TL ( 0x3C) // I2C Transmit FIFO Threshold +#define R_IC_CLR_INTR ( 0x40) // Clear Combined and Individual Interrupts +#define R_IC_CLR_RX_UNDER ( 0x44) // Clear RX_UNDER Interrupt +#define R_IC_CLR_RX_OVER ( 0x48) // Clear RX_OVERinterrupt +#define R_IC_CLR_TX_OVER ( 0x4C) // Clear TX_OVER interrupt +#define R_IC_CLR_RD_REQ ( 0x50) // Clear RD_REQ interrupt +#define R_IC_CLR_TX_ABRT ( 0x54) // Clear TX_ABRT interrupt +#define R_IC_CLR_RX_DONE ( 0x58) // Clear RX_DONE interrupt +#define R_IC_CLR_ACTIVITY ( 0x5C) // Clear ACTIVITY interrupt +#define R_IC_CLR_STOP_DET ( 0x60) // Clear STOP_DET interrupt +#define R_IC_CLR_START_DET ( 0x64) // Clear START_DET interrupt +#define R_IC_CLR_GEN_CALL ( 0x68) // Clear GEN_CALL interrupt +#define R_IC_ENABLE ( 0x6C) // I2C Enable +#define R_IC_STATUS ( 0x70) // I2C Status + +#define R_IC_SDA_HOLD ( 0x7C) // I2C IC_DEFAULT_SDA_HOLD//16bits + +#define STAT_MST_ACTIVITY BIT5 // Master FSM Activity Status. +#define STAT_RFF BIT4 // RX FIFO is completely full +#define STAT_RFNE BIT3 // RX FIFO is not empty +#define STAT_TFE BIT2 // TX FIFO is completely empty +#define STAT_TFNF BIT1 // TX FIFO is not full + +#define R_IC_TXFLR ( 0x74) // Transmit FIFO Level Register +#define R_IC_RXFLR ( 0x78) // Receive FIFO Level Register +#define R_IC_TX_ABRT_SOURCE ( 0x80) // I2C Transmit Abort Status Register +#define R_IC_SLV_DATA_NACK_ONLY ( 0x84) // Generate SLV_DATA_NACK Register +#define R_IC_DMA_CR ( 0x88) // DMA Control Register +#define R_IC_DMA_TDLR ( 0x8C) // DMA Transmit Data Level +#define R_IC_DMA_RDLR ( 0x90) // DMA Receive Data Level +#define R_IC_SDA_SETUP ( 0x94) // I2C SDA Setup Register +#define R_IC_ACK_GENERAL_CALL ( 0x98) // I2C ACK General Call Register +#define R_IC_ENABLE_STATUS ( 0x9C) // I2C Enable Status Register +#define R_IC_COMP_PARAM ( 0xF4) // Component Parameter Register +#define R_IC_COMP_VERSION ( 0xF8) // Component Version ID +#define R_IC_COMP_TYPE ( 0xFC) // Component Type + +#define R_IC_CLK_GATE ( 0xC0) // Clock Gate + +#define I2C_SS_SCL_HCNT_VALUE_100M 0x1DD +#define I2C_SS_SCL_LCNT_VALUE_100M 0x1E4 +#define I2C_FS_SCL_HCNT_VALUE_100M 0x54 +#define I2C_FS_SCL_LCNT_VALUE_100M 0x9a +#define I2C_HS_SCL_HCNT_VALUE_100M 0x7 +#define I2C_HS_SCL_LCNT_VALUE_100M 0xE + +#define IC_TAR_10BITADDR_MASTER BIT12 +#define FIFO_SIZE 32 +#define R_IC_INTR_STAT ( 0x2C) // I2c Inetrrupt Status +#define R_IC_INTR_MASK ( 0x30) // I2c Interrupt Mask +#define I2C_INTR_GEN_CALL BIT11 // General call received +#define I2C_INTR_START_DET BIT10 +#define I2C_INTR_STOP_DET BIT9 +#define I2C_INTR_ACTIVITY BIT8 +#define I2C_INTR_TX_ABRT BIT6 // Set on NACK +#define I2C_INTR_TX_EMPTY BIT4 +#define I2C_INTR_TX_OVER BIT3 +#define I2C_INTR_RX_FULL BIT2 // Data bytes in RX FIFO over threshold +#define I2C_INTR_RX_OVER BIT1 +#define I2C_INTR_RX_UNDER BIT0 + +EFI_STATUS ProgramPciLpssI2C ( + IN UINT8 BusNo + ); +EFI_STATUS ByteReadI2C_Basic( + IN UINT8 BusNo, + IN UINT8 SlaveAddress, + IN UINTN ReadBytes, + OUT UINT8 *ReadBuffer, + IN UINT8 Start, + IN UINT8 End + ); +EFI_STATUS ByteWriteI2C_Basic( + IN UINT8 BusNo, + IN UINT8 SlaveAddress, + IN UINTN WriteBytes, + IN UINT8 *WriteBuffer, + IN UINT8 Start, + IN UINT8 End + ); + +EFI_STATUS ByteReadI2C( + IN UINT8 BusNo, + IN UINT8 SlaveAddress, + IN UINT8 Offset, + IN UINTN ReadBytes, + OUT UINT8 *ReadBuffer + ); +EFI_STATUS ByteWriteI2C( + IN UINT8 BusNo, + IN UINT8 SlaveAddress, + IN UINT8 Offset, + IN UINTN WriteBytes, + IN UINT8 *WriteBuffer + ); + +#endif // I2C_REGS_A0_H diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Library/PchPlatformLib.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Library/PchPlatformLib.h new file mode 100644 index 0000000000..8f0ca027b4 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Library/PchPlatformLib.h @@ -0,0 +1,121 @@ +/** +**/ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + @file + PchPlatformLib.h + + @brief + Header file for PchPlatform Lib. + +**/ +#ifndef _PCH_PLATFORM_LIB_H_ +#define _PCH_PLATFORM_LIB_H_ + +/// +/// Timeout value used when Sending / Receiving messages. +/// NOTE: this must cover the longest possible wait time +/// between message being sent and response being available. +/// e.g. Virtual function readiness might take some time. +/// +VOID +EFIAPI +PchPmTimerStall ( + IN UINTN Microseconds + ) +/** + + @brief + Delay for at least the request number of microseconds. + This function would be called by runtime driver, please do not use any MMIO marco here. + + @param[in] Microseconds Number of microseconds to delay. + + @retval NONE + +**/ +; + +BOOLEAN +EFIAPI +PchIsSpiDescriptorMode ( + IN UINTN SpiBase + ) +/** + + @brief + Check whether SPI is in descriptor mode + + @param[in] SpiBase The PCH Spi Base Address + + @retval TRUE SPI is in descriptor mode + @retval FALSE SPI is not in descriptor mode + +**/ +; + +PCH_STEPPING +EFIAPI +PchStepping ( + VOID + ) +/** + + @brief + Return Pch stepping type + + @param[in] None + + @retval PCH_STEPPING Pch stepping type + +**/ +; + +BOOLEAN +IsPchSupported ( + VOID + ) +/** + + @brief + Determine if PCH is supported + + @param[in] None + + @retval TRUE PCH is supported + @retval FALSE PCH is not supported + +**/ +; + +VOID +EFIAPI +PchAlternateAccessMode ( + IN UINTN IlbBase, + IN BOOLEAN AmeCtrl + ) +/** + + This function can be called to enable/disable Alternate Access Mode + + @param[in] IlbBase The PCH ILB Base Address + @param[in] AmeCtrl If TRUE, enable Alternate Access Mode. + If FALSE, disable Alternate Access Mode. + + @retval NONE + +**/ +; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchAccess.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchAccess.h new file mode 100644 index 0000000000..3f44d2bfa9 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchAccess.h @@ -0,0 +1,526 @@ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchAccess.h + + @brief + Macros that simplify accessing PCH devices's PCI registers. + + ** NOTE ** these macros assume the PCH device is on BUS 0 + +**/ +#ifndef _PCH_ACCESS_H_ +#define _PCH_ACCESS_H_ + +#include "PchRegs.h" +#include "PchCommonDefinitions.h" + +#ifndef STALL_ONE_MICRO_SECOND +#define STALL_ONE_MICRO_SECOND 1 +#endif +#ifndef STALL_ONE_SECOND +#define STALL_ONE_SECOND 1000000 +#endif + +/// +/// Memory Mapped PCI Access macros +/// +/// +/// PCI Device MM Base +/// +#ifndef MmPciAddress +#define MmPciAddress(Segment, Bus, Device, Function, Register) \ + ((UINTN) PatchPcdGet64 (PcdPciExpressBaseAddress) + \ + (UINTN) (Bus << 20) + \ + (UINTN) (Device << 15) + \ + (UINTN) (Function << 12) + \ + (UINTN) (Register) \ + ) +#endif +/// +/// Pch Controller PCI access macros +/// +#define PCH_RCRB_BASE ( \ + MmioRead32 (MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_LPC, \ + PCI_FUNCTION_NUMBER_PCH_LPC), \ + R_PCH_LPC_RCBA)) & B_PCH_LPC_RCBA_BAR \ + ) + +/// +/// Device 0x1b, Function 0 +/// +#define PchAzaliaPciCfg32(Register) \ + MmioRead32 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_AZALIA, \ + 0, \ + Register) \ + ) + +#define PchAzaliaPciCfg32Or(Register, OrData) \ + MmioOr32 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_AZALIA, \ + 0, \ + Register), \ + OrData \ + ) + +#define PchAzaliaPciCfg32And(Register, AndData) \ + MmioAnd32 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_AZALIA, \ + 0, \ + Register), \ + AndData \ + ) + +#define PchAzaliaPciCfg32AndThenOr(Register, AndData, OrData) \ + MmioAndThenOr32 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_AZALIA, \ + 0, \ + Register), \ + OrData \ + ) + +#define PchAzaliaPciCfg16(Register) \ + MmioRead16 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_AZALIA, \ + 0, \ + Register) \ + ) + +#define PchAzaliaPciCfg16Or(Register, OrData) \ + MmioOr16 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_AZALIA, \ + 0, \ + Register), \ + OrData \ + ) + +#define PchAzaliaPciCfg16And(Register, AndData) \ + MmioAnd16 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_AZALIA, \ + 0, \ + Register), \ + AndData \ + ) + +#define PchAzaliaPciCfg16AndThenOr(Register, AndData, OrData) \ + MmioAndThenOr16 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_AZALIA, \ + 0, \ + Register), \ + AndData, \ + OrData \ + ) + +#define PchAzaliaPciCfg8(Register) MmioRead8 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_AZALIA, 0, Register)) + +#define PchAzaliaPciCfg8Or(Register, OrData) \ + MmioOr8 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_AZALIA, \ + 0, \ + Register), \ + OrData \ + ) + +#define PchAzaliaPciCfg8And(Register, AndData) \ + MmioAnd8 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_AZALIA, \ + 0, \ + Register), \ + AndData \ + ) + +#define PchAzaliaPciCfg8AndThenOr(Register, AndData, OrData) \ + MmioAndThenOr8 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_AZALIA, \ + 0, \ + Register), \ + AndData, \ + OrData \ + ) + +/// +/// Device 0x1f, Function 0 +/// +#define PchLpcPciCfg32(Register) MmioRead32 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, Register)) + +#define PchLpcMmioOr32 (Register, OrData) \ + MmioOr32 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_LPC, \ + 0, \ + Register), \ + OrData \ + ) + +#define PchLpcPciCfg32And(Register, AndData) \ + MmioAnd32 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_LPC, \ + 0, \ + Register), \ + AndData \ + ) + +#define PchLpcPciCfg32AndThenOr(Register, AndData, OrData) \ + MmioAndThenOr32 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_LPC, \ + 0, \ + Register), \ + AndData, \ + OrData \ + ) + +#define PchLpcPciCfg16(Register) MmioRead16 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, Register)) + +#define PchLpcPciCfg16Or(Register, OrData) \ + MmioOr16 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_LPC, \ + 0, \ + Register), \ + OrData \ + ) + +#define PchLpcPciCfg16And(Register, AndData) \ + MmioAndThenOr16 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_LPC, \ + 0, \ + Register), \ + AndData \ + ) + +#define PchLpcPciCfg16AndThenOr(Register, AndData, OrData) \ + MmioAndThenOr16 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_LPC, \ + 0, \ + Register), \ + AndData, \ + OrData \ + ) + +#define PchLpcPciCfg8(Register) MmioRead8 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, Register)) + +#define PchLpcPciCfg8Or(Register, OrData) \ + MmioOr8 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_LPC, \ + 0, \ + Register), \ + OrData \ + ) + +#define PchLpcPciCfg8And(Register, AndData) \ + MmioAnd8 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_LPC, \ + 0, \ + Register), \ + AndData \ + ) + +#define PchLpcPciCfg8AndThenOr(Register, AndData, OrData) \ + MmioAndThenOr8 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_LPC, \ + 0, \ + Register), \ + AndData, \ + OrData \ + ) + + +/// +/// SATA device 0x13, Function 0 +/// +#define PchSataPciCfg32(Register) MmioRead32 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SATA, PCI_FUNCTION_NUMBER_PCH_SATA, Register)) + +#define PchSataPciCfg32Or(Register, OrData) \ + MmioOr32 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_SATA, \ + PCI_FUNCTION_NUMBER_PCH_SATA, \ + Register), \ + OrData \ + ) + +#define PchSataPciCfg32And(Register, AndData) \ + MmioAnd32 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_SATA, \ + PCI_FUNCTION_NUMBER_PCH_SATA, \ + Register), \ + AndData \ + ) + +#define PchSataPciCfg32AndThenOr(Register, AndData, OrData) \ + MmioAndThenOr32 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_SATA, \ + PCI_FUNCTION_NUMBER_PCH_SATA, \ + Register), \ + AndData, \ + OrData \ + ) + +#define PchSataPciCfg16(Register) MmioRead16 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SATA, PCI_FUNCTION_NUMBER_PCH_SATA, Register)) + +#define PchSataPciCfg16Or(Register, OrData) \ + MmioOr16 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_SATA, \ + PCI_FUNCTION_NUMBER_PCH_SATA, \ + Register), \ + OrData \ + ) + +#define PchSataPciCfg16And(Register, AndData) \ + MmioAndThenOr16 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_SATA, \ + PCI_FUNCTION_NUMBER_PCH_SATA, \ + Register), \ + AndData \ + ) + +#define PchSataPciCfg16AndThenOr(Register, AndData, OrData) \ + MmioAndThenOr16 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_SATA, \ + PCI_FUNCTION_NUMBER_PCH_SATA, \ + Register), \ + AndData, \ + OrData \ + ) + +#define PchSataPciCfg8(Register) MmioRead8 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SATA, PCI_FUNCTION_NUMBER_PCH_SATA, Register)) + +#define PchSataPciCfg8Or(Register, OrData) \ + MmioOr8 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_SATA, \ + PCI_FUNCTION_NUMBER_PCH_SATA, \ + Register), \ + OrData \ + ) + +#define PchSataPciCfg8And(Register, AndData) \ + MmioAnd8 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_SATA, \ + PCI_FUNCTION_NUMBER_PCH_SATA, \ + Register), \ + AndData \ + ) + +#define PchSataPciCfg8AndThenOr(Register, AndData, OrData) \ + MmioAndThenOr8 ( \ + MmPciAddress (0, \ + DEFAULT_PCI_BUS_NUMBER_PCH, \ + PCI_DEVICE_NUMBER_PCH_SATA, \ + PCI_FUNCTION_NUMBER_PCH_SATA, \ + Register), \ + AndData, \ + OrData \ + ) + + +/// +/// Root Complex Register Block +/// +#define PchMmRcrb32(Register) MmioRead32 (PCH_RCRB_BASE + Register) + +#define PchMmRcrb32Or(Register, OrData) MmioOr32 (PCH_RCRB_BASE + Register, OrData) + +#define PchMmRcrb32And(Register, AndData) MmioAnd32 (PCH_RCRB_BASE + Register, AndData) + +#define PchMmRcrb32AndThenOr(Register, AndData, OrData) MmioAndThenOr32 (PCH_RCRB_BASE + Register, AndData, OrData) + +#define PchMmRcrb16(Register) MmioRead16 (PCH_RCRB_BASE + Register) + +#define PchMmRcrb16Or(Register, OrData) MmioOr16 (PCH_RCRB_BASE + Register, OrData) + +#define PchMmRcrb16And(Register, AndData) MmioAnd16 (PCH_RCRB_BASE + Register, AndData) + +#define PchMmRcrb16AndThenOr(Register, AndData, OrData) MmioAndThenOr16 (PCH_RCRB_BASE + Register, AndData, OrData) + +#define PchMmRcrb8(Register) MmioRead8 (PCH_RCRB_BASE + Register) + +#define PchMmRcrb8Or(Register, OrData) MmioOr8 (PCH_RCRB_BASE + Register, OrData) + +#define PchMmRcrb8And(Register, AndData) MmioAnd8 (PCH_RCRB_BASE + Register, AndData) + +#define PchMmRcrb8AndThenOr(Register, AndData, OrData) MmioAndThenOr8 (PCH_RCRB_BASE + Register, AndData, OrData) + + +/// +/// Message Bus +/// + +/// +/// Message Bus Registers +/// +#define MC_MCR 0x000000D0 // Cunit Message Control Register +#define MC_MDR 0x000000D4 // Cunit Message Data Register +#define MC_MCRX 0x000000D8 // Cunit Message Control Register Extension + +/// +/// Message Bus API +/// +#define MSG_BUS_ENABLED 0x000000F0 +#define MSGBUS_MASKHI 0xFFFFFF00 +#define MSGBUS_MASKLO 0x000000FF +#define MESSAGE_DWORD_EN BIT4 | BIT5 | BIT6 | BIT7 + +#define PchMsgBusRead32(PortId, Register, Dbuff, ReadOpCode, WriteOpCode) \ +{ \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX), (UINT32) (Register & MSGBUS_MASKHI)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR ), (UINT32) ((ReadOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN)); \ + (Dbuff) = MmioRead32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR)); \ +} + +#define PchMsgBusAnd32(PortId, Register, Dbuff, AndData, ReadOpCode, WriteOpCode) \ +{ \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX), (UINT32) (Register & MSGBUS_MASKHI)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR ), (UINT32) ((ReadOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN)); \ + (Dbuff) = MmioRead32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX), (UINT32) (Register & MSGBUS_MASKHI)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR ), (UINT32) (Dbuff & AndData)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR ), (UINT32) ((WriteOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN)); \ +} + +#define PchMsgBusOr32(PortId, Register, Dbuff, OrData, ReadOpCode, WriteOpCode) \ +{ \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX), (UINT32) (Register & MSGBUS_MASKHI)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR ), (UINT32) ((ReadOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN)); \ + (Dbuff) = MmioRead32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX), (UINT32) (Register & MSGBUS_MASKHI)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR ), (UINT32) (Dbuff | OrData)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR ), (UINT32) ((WriteOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN)); \ +} + +#define PchMsgBusAndThenOr32(PortId, Register, Dbuff, AndData, OrData, ReadOpCode, WriteOpCode) \ +{ \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX), (UINT32) (Register & MSGBUS_MASKHI)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR ), (UINT32) ((ReadOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN)); \ + (Dbuff) = MmioRead32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX), (UINT32) (Register & MSGBUS_MASKHI)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR ), (UINT32) ((Dbuff & AndData) | OrData)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR ), (UINT32) ((WriteOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN)); \ +} + +typedef struct _PCH_MSG_BUS_TABLE_STRUCT { + UINT32 PortId; + UINT32 Address; + UINT32 AndMask; + UINT32 OrMask; + UINT32 ReadOpCode; + UINT32 WriteOpCode; +} PCH_MSG_BUS_TABLE_STRUCT_TABLE_STRUCT; + +#ifndef _S3SUPPORT_ +#define _S3SUPPORT_ +UINTN MCRX; +UINTN MCR; +// +// In S3 execute, we should follow the MSG BUS access procedure to restore the saving data. +// To do so, we adopt READ ->> SAVE +// Indirect IO access: (According BayTrail-M EDS chapter 3.6) +// 1. Write Index port into MSG BUS_MCRX first. +// 2. Write content to data register which is called MSG BUS_MDR. +// 3. Send "message bus control" to complete the procedure. +// +#define S3BootScriptSaveMsgBusToMemWrite(PortId, Register, Dbuff, ReadOpCode, WriteOpCode) \ +{ \ + MCRX = (UINTN) Register & MSGBUS_MASKHI; \ + MCR = (UINTN) ((ReadOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX), (UINT32) MCRX); \ + S3BootScriptSaveMemWrite(EfiBootScriptWidthUint32, (UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX),1, (VOID *) (UINTN) &MCRX); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR ), (UINT32) MCR); \ + (Dbuff) = (UINT32) MmioRead32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR)); \ + S3BootScriptSaveMemWrite(EfiBootScriptWidthUint32, (UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR),1, (VOID *) &Dbuff); \ + MCR = (UINTN) ((WriteOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN); \ + S3BootScriptSaveMemWrite(EfiBootScriptWidthUint32, (UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR),1, (VOID *) (UINTN) &MCR); \ +} + +// +// This macro combines two function: 1. PchMsgBusAndThenOr32 () 2. S3 boot script save +// +#define PchMsgBusAndThenOr32AddToS3Save(PortId, Register, Dbuff, AndData, OrData, ReadOpCode, WriteOpCode) \ +{ \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX), (UINT32) (Register & MSGBUS_MASKHI)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR ), (UINT32) ((ReadOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN)); \ + (Dbuff) = (UINT32) MmioRead32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX), (UINT32) (Register & MSGBUS_MASKHI)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR ), (UINT32) ((Dbuff & AndData) | OrData)); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR ), (UINT32) ((WriteOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN)); \ + MCRX = (UINTN) Register & MSGBUS_MASKHI; \ + MCR = (UINTN) ((ReadOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX), (UINT32) MCRX); \ + S3BootScriptSaveMemWrite(EfiBootScriptWidthUint32, (UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCRX),1,(VOID *) (UINTN) &MCRX); \ + MmioWrite32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR ), (UINT32) MCR); \ + (Dbuff) = (UINT32) MmioRead32 ((UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR)); \ + S3BootScriptSaveMemWrite(EfiBootScriptWidthUint32, (UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MDR),1,(VOID *) &Dbuff); \ + MCR = (UINTN) ((WriteOpCode << 24) | (PortId << 16) | ((Register & MSGBUS_MASKLO) << 8) | MESSAGE_DWORD_EN); \ + S3BootScriptSaveMemWrite(EfiBootScriptWidthUint32, (UINTN) (PatchPcdGet64 (PcdPciExpressBaseAddress) + MC_MCR),1,(VOID *) (UINTN) &MCR); \ +} + +#endif + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchCommonDefinitions.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchCommonDefinitions.h new file mode 100644 index 0000000000..29002cc842 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchCommonDefinitions.h @@ -0,0 +1,216 @@ +/*++ + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PchCommonDefinitions.h + +Abstract: + + This header file provides common definitions for PCH + +--*/ +#ifndef _PCH_COMMON_DEFINITIONS_H_ +#define _PCH_COMMON_DEFINITIONS_H_ + +// +// MMIO access macros +// +#define PchMmioAddress(BaseAddr, Register) ((UINTN) BaseAddr + (UINTN) (Register)) + +// +// 32 bit MMIO access +// +#define PchMmio32Ptr(BaseAddr, Register) ((volatile UINT32 *) PchMmioAddress (BaseAddr, Register)) + +#define PchMmio32(BaseAddr, Register) *PchMmio32Ptr (BaseAddr, Register) + +#define PchMmio32Or(BaseAddr, Register, OrData) \ + PchMmio32 (BaseAddr, Register) = (UINT32) \ + (PchMmio32 (BaseAddr, Register) | (UINT32) (OrData)) + +#define PchMmio32And(BaseAddr, Register, AndData) \ + PchMmio32 (BaseAddr, Register) = (UINT32) \ + (PchMmio32 (BaseAddr, Register) & (UINT32) (AndData)) + +#define PchMmio32AndThenOr(BaseAddr, Register, AndData, OrData) \ + PchMmio32 (BaseAddr, Register) = (UINT32) \ + ((PchMmio32 (BaseAddr, Register) & (UINT32) (AndData)) | (UINT32) (OrData)) + +// +// 16 bit MMIO access +// +#define PchMmio16Ptr(BaseAddr, Register) ((volatile UINT16 *) PchMmioAddress (BaseAddr, Register)) + +#define PchMmio16(BaseAddr, Register) *PchMmio16Ptr (BaseAddr, Register) + +#define PchMmio16Or(BaseAddr, Register, OrData) \ + PchMmio16 (BaseAddr, Register) = (UINT16) \ + (PchMmio16 (BaseAddr, Register) | (UINT16) (OrData)) + +#define PchMmio16And(BaseAddr, Register, AndData) \ + PchMmio16 (BaseAddr, Register) = (UINT16) \ + (PchMmio16 (BaseAddr, Register) & (UINT16) (AndData)) + +#define PchMmio16AndThenOr(BaseAddr, Register, AndData, OrData) \ + PchMmio16 (BaseAddr, Register) = (UINT16) \ + ((PchMmio16 (BaseAddr, Register) & (UINT16) (AndData)) | (UINT16) (OrData)) + +// +// 8 bit MMIO access +// +#define PchMmio8Ptr(BaseAddr, Register) ((volatile UINT8 *) PchMmioAddress (BaseAddr, Register)) + +#define PchMmio8(BaseAddr, Register) *PchMmio8Ptr (BaseAddr, Register) + +#define PchMmio8Or(BaseAddr, Register, OrData) \ + PchMmio8 (BaseAddr, Register) = (UINT8) \ + (PchMmio8 (BaseAddr, Register) | (UINT8) (OrData)) + +#define PchMmio8And(BaseAddr, Register, AndData) \ + PchMmio8 (BaseAddr, Register) = (UINT8) \ + (PchMmio8 (BaseAddr, Register) & (UINT8) (AndData)) + +#define PchMmio8AndThenOr(BaseAddr, Register, AndData, OrData) \ + PchMmio8 (BaseAddr, Register) = (UINT8) \ + ((PchMmio8 (BaseAddr, Register) & (UINT8) (AndData)) | (UINT8) (OrData)) + +// +// Memory Mapped PCI Access macros +// +#define PCH_PCI_EXPRESS_BASE_ADDRESS 0xE0000000 +// +// PCI Device MM Base +// +#define PchPciDeviceMmBase(Bus, Device, Function) \ + ( \ + (UINTN) PCH_PCI_EXPRESS_BASE_ADDRESS + (UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) \ + (Function << 12) \ + ) + +// +// PCI Device MM Address +// +#define PchPciDeviceMmAddress(Segment, Bus, Device, Function, Register) \ + ( \ + (UINTN) PCH_PCI_EXPRESS_BASE_ADDRESS + (UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) \ + (Function << 12) + (UINTN) (Register) \ + ) + +// +// 32 bit PCI access +// +#define PchMmPci32Ptr(Segment, Bus, Device, Function, Register) \ + ((volatile UINT32 *) PchPciDeviceMmAddress (Segment, Bus, Device, Function, Register)) + +#define PchMmPci32(Segment, Bus, Device, Function, Register) *PchMmPci32Ptr (Segment, Bus, Device, Function, Register) + +#define PchMmPci32Or(Segment, Bus, Device, Function, Register, OrData) \ + PchMmPci32 ( \ + Segment, \ + Bus, \ + Device, \ + Function, \ + Register \ + ) = (UINT32) (PchMmPci32 (Segment, Bus, Device, Function, Register) | (UINT32) (OrData)) + +#define PchMmPci32And(Segment, Bus, Device, Function, Register, AndData) \ + PchMmPci32 ( \ + Segment, \ + Bus, \ + Device, \ + Function, \ + Register \ + ) = (UINT32) (PchMmPci32 (Segment, Bus, Device, Function, Register) & (UINT32) (AndData)) + +#define PchMmPci32AndThenOr(Segment, Bus, Device, Function, Register, AndData, OrData) \ + PchMmPci32 ( \ + Segment, \ + Bus, \ + Device, \ + Function, \ + Register \ + ) = (UINT32) ((PchMmPci32 (Segment, Bus, Device, Function, Register) & (UINT32) (AndData)) | (UINT32) (OrData)) + +// +// 16 bit PCI access +// +#define PchMmPci16Ptr(Segment, Bus, Device, Function, Register) \ + ((volatile UINT16 *) PchPciDeviceMmAddress (Segment, Bus, Device, Function, Register)) + +#define PchMmPci16(Segment, Bus, Device, Function, Register) *PchMmPci16Ptr (Segment, Bus, Device, Function, Register) + +#define PchMmPci16Or(Segment, Bus, Device, Function, Register, OrData) \ + PchMmPci16 ( \ + Segment, \ + Bus, \ + Device, \ + Function, \ + Register \ + ) = (UINT16) (PchMmPci16 (Segment, Bus, Device, Function, Register) | (UINT16) (OrData)) + +#define PchMmPci16And(Segment, Bus, Device, Function, Register, AndData) \ + PchMmPci16 ( \ + Segment, \ + Bus, \ + Device, \ + Function, \ + Register \ + ) = (UINT16) (PchMmPci16 (Segment, Bus, Device, Function, Register) & (UINT16) (AndData)) + +#define PchMmPci16AndThenOr(Segment, Bus, Device, Function, Register, AndData, OrData) \ + PchMmPci16 ( \ + Segment, \ + Bus, \ + Device, \ + Function, \ + Register \ + ) = (UINT16) ((PchMmPci16 (Segment, Bus, Device, Function, Register) & (UINT16) (AndData)) | (UINT16) (OrData)) + +// +// 8 bit PCI access +// +#define PchMmPci8Ptr(Segment, Bus, Device, Function, Register) \ + ((volatile UINT8 *) PchPciDeviceMmAddress (Segment, Bus, Device, Function, Register)) + +#define PchMmPci8(Segment, Bus, Device, Function, Register) *PchMmPci8Ptr (Segment, Bus, Device, Function, Register) + +#define PchMmPci8Or(Segment, Bus, Device, Function, Register, OrData) \ + PchMmPci8 ( \ + Segment, \ + Bus, \ + Device, \ + Function, \ + Register \ + ) = (UINT8) (PchMmPci8 (Segment, Bus, Device, Function, Register) | (UINT8) (OrData)) + +#define PchMmPci8And(Segment, Bus, Device, Function, Register, AndData) \ + PchMmPci8 ( \ + Segment, \ + Bus, \ + Device, \ + Function, \ + Register \ + ) = (UINT8) (PchMmPci8 (Segment, Bus, Device, Function, Register) & (UINT8) (AndData)) + +#define PchMmPci8AndThenOr(Segment, Bus, Device, Function, Register, AndData, OrData) \ + PchMmPci8 ( \ + Segment, \ + Bus, \ + Device, \ + Function, \ + Register \ + ) = (UINT8) ((PchMmPci8 (Segment, Bus, Device, Function, Register) & (UINT8) (AndData)) | (UINT8) (OrData)) + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs.h new file mode 100644 index 0000000000..21ca877bd1 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs.h @@ -0,0 +1,211 @@ +/** + +Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchRegs.h + + @brief + Register names for VLV SC. + + Conventions: + + - Prefixes: + 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 + - In general, PCH registers are denoted by "_PCH_" in register names + - Registers / bits that are different between PCH generations are denoted by + "_PCH__" in register/bit names. e.g., "_PCH_VLV_" + - Registers / bits that are different between SKUs are denoted by "_" + at the end of the register/bit names + - Registers / bits of new devices introduced in a PCH generation will be just named + as "_PCH_" without inserted. + +**/ +#ifndef _PCH_REGS_H_ +#define _PCH_REGS_H_ + +/// +/// Bit Definitions. BUGBUG: drive these definitions to code base. Should not need +/// to be part of chipset modules +/// +#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 +#define BIT32 0x100000000 +#define BIT33 0x200000000 +#define BIT34 0x400000000 +#define BIT35 0x800000000 +#define BIT36 0x1000000000 +#define BIT37 0x2000000000 +#define BIT38 0x4000000000 +#define BIT39 0x8000000000 +#define BIT40 0x10000000000 +#define BIT41 0x20000000000 +#define BIT42 0x40000000000 +#define BIT43 0x80000000000 +#define BIT44 0x100000000000 +#define BIT45 0x200000000000 +#define BIT46 0x400000000000 +#define BIT47 0x800000000000 +#define BIT48 0x1000000000000 +#define BIT49 0x2000000000000 +#define BIT50 0x4000000000000 +#define BIT51 0x8000000000000 +#define BIT52 0x10000000000000 +#define BIT53 0x20000000000000 +#define BIT54 0x40000000000000 +#define BIT55 0x80000000000000 +#define BIT56 0x100000000000000 +#define BIT57 0x200000000000000 +#define BIT58 0x400000000000000 +#define BIT59 0x800000000000000 +#define BIT60 0x1000000000000000 +#define BIT61 0x2000000000000000 +#define BIT62 0x4000000000000000 +#define BIT63 0x8000000000000000 +#endif +/// +/// The default PCH PCI bus number +/// +#define DEFAULT_PCI_BUS_NUMBER_PCH 0 + +/// +/// Default Vendor ID and Subsystem ID +/// +#define V_PCH_INTEL_VENDOR_ID 0x8086 +#define V_PCH_DEFAULT_SID 0x7270 +#define V_PCH_DEFAULT_SVID_SID (V_PCH_INTEL_VENDOR_ID + (V_PCH_DEFAULT_SID << 16)) + +/// +/// Include device register definitions +/// +#include "PchRegs/PchRegsHda.h" +#include "PchRegs/PchRegsLpss.h" +#include "PchRegs/PchRegsPcie.h" +#include "PchRegs/PchRegsPcu.h" +#include "PchRegs/PchRegsRcrb.h" +#include "PchRegs/PchRegsSata.h" +#include "PchRegs/PchRegsScc.h" +#include "PchRegs/PchRegsSmbus.h" +#include "PchRegs/PchRegsSpi.h" +#include "PchRegs/PchRegsUsb.h" +//#include "PchRegs/PchRegsLpe.h" + +/// +/// Device IDS that are PCH Server specific +/// +#define IS_PCH_DEVICE_ID(DeviceId) \ + ( \ + (DeviceId == V_PCH_LPC_DEVICE_ID_0) || \ + (DeviceId == V_PCH_LPC_DEVICE_ID_1) || \ + (DeviceId == V_PCH_LPC_DEVICE_ID_2) || \ + (DeviceId == V_PCH_LPC_DEVICE_ID_3) \ + ) + +#define IS_PCH_VLV_LPC_DEVICE_ID(DeviceId) \ + ( \ + IS_PCH_DEVICE_ID (DeviceId) \ + ) + +#define IS_PCH_VLV_SATA_DEVICE_ID(DeviceId) \ + ( \ + IS_PCH_VLV_SATA_AHCI_DEVICE_ID (DeviceId) || \ + IS_PCH_VLV_SATA_MODE_DEVICE_ID (DeviceId) || \ + IS_PCH_VLV_SATA_RAID_DEVICE_ID (DeviceId) \ + ) + +#define IS_PCH_VLV_SATA_AHCI_DEVICE_ID(DeviceId) \ + ( \ + (DeviceId == V_PCH_SATA_DEVICE_ID_D_AHCI) || \ + (DeviceId == V_PCH_SATA_DEVICE_ID_M_AHCI) \ + ) + +#define IS_PCH_VLV_SATA_RAID_DEVICE_ID(DeviceId) \ + ( \ + (DeviceId == V_PCH_SATA_DEVICE_ID_D_RAID) || \ + (DeviceId == V_PCH_SATA_DEVICE_ID_M_RAID) \ + ) + +#define IS_PCH_VLV_SATA_MODE_DEVICE_ID(DeviceId) \ + ( \ + (DeviceId == V_PCH_SATA_DEVICE_ID_D_IDE) || \ + (DeviceId == V_PCH_SATA_DEVICE_ID_M_IDE) \ + ) +#define IS_PCH_VLV_USB_DEVICE_ID(DeviceId) \ + ( \ + (DeviceId == V_PCH_USB_DEVICE_ID_0) || \ + (DeviceId == V_PCH_USB_DEVICE_ID_1) \ + ) +#define IS_PCH_VLV_PCIE_DEVICE_ID(DeviceId) \ + ( \ + (DeviceId == V_PCH_PCIE_DEVICE_ID_0) || \ + (DeviceId == V_PCH_PCIE_DEVICE_ID_1) || \ + (DeviceId == V_PCH_PCIE_DEVICE_ID_2) || \ + (DeviceId == V_PCH_PCIE_DEVICE_ID_3) || \ + (DeviceId == V_PCH_PCIE_DEVICE_ID_4) || \ + (DeviceId == V_PCH_PCIE_DEVICE_ID_5) || \ + (DeviceId == V_PCH_PCIE_DEVICE_ID_6) || \ + (DeviceId == V_PCH_PCIE_DEVICE_ID_7) \ + ) + +/// +/// Any device ID that is Valleyview SC +/// +#define IS_PCH_VLV_DEVICE_ID(DeviceId) \ + ( \ + IS_PCH_VLV_LPC_DEVICE_ID (DeviceId) || \ + IS_PCH_VLV_SATA_DEVICE_ID (DeviceId) || \ + IS_PCH_VLV_USB_DEVICE_ID (DeviceId) || \ + IS_PCH_VLV_PCIE_DEVICE_ID (DeviceId) || \ + (DeviceId) == V_PCH_SMBUS_DEVICE_ID || \ + (DeviceId) == V_PCH_HDA_DEVICE_ID_0 || \ + (DeviceId) == V_PCH_HDA_DEVICE_ID_1 \ + ) + +#define IS_SUPPORTED_DEVICE_ID(DeviceId) IS_PCH_VLV_DEVICE_ID (DeviceId) + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsHda.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsHda.h new file mode 100644 index 0000000000..5d68925cb5 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsHda.h @@ -0,0 +1,56 @@ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchRegsHda.h + + @brief + Register names for PCH High Definition Audio device. + + Conventions: + + - Prefixes: + 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 + - In general, PCH registers are denoted by "_PCH_" in register names + - Registers / bits that are different between PCH generations are denoted by + "_PCH__" in register/bit names. e.g., "_PCH_VLV_" + - Registers / bits that are different between SKUs are denoted by "_" + at the end of the register/bit names + - Registers / bits of new devices introduced in a PCH generation will be just named + as "_PCH_" without inserted. + +**/ +#ifndef _PCH_REGS_HDA_H_ +#define _PCH_REGS_HDA_H_ + +/// +/// Azalia Controller Registers (D27:F0) +/// +#define PCI_DEVICE_NUMBER_PCH_AZALIA 27 +#define PCI_FUNCTION_NUMBER_PCH_AZALIA 0 + +#define R_PCH_HDA_PCS 0x54 // Power Management Control and Status +#define B_PCH_HDA_PCS_DATA 0xFF000000 // Data, does not apply +#define B_PCH_HDA_PCS_CCE BIT23 // Bus Power Control Enable, does not apply +#define B_PCH_HDA_PCS_PMES BIT15 // PME Status +#define B_PCH_HDA_PCS_PMEE BIT8 // PME Enable +#define B_PCH_HDA_PCS_PS (BIT1 | BIT0) // Power State - D0/D3 Hot +#define V_PCH_HDA_PCS_PS0 0x00 +#define V_PCH_HDA_PCS_PS3 0x03 + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsLpss.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsLpss.h new file mode 100644 index 0000000000..4e3cd6c311 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsLpss.h @@ -0,0 +1,492 @@ +/*++ + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PchRegsLpss.h + +Abstract: + + Register names for VLV Low Input Output (LPSS) module. + + Conventions: + + - Prefixes: + 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 + - In general, PCH registers are denoted by "_PCH_" in register names + - Registers / bits that are different between PCH generations are denoted by + "_PCH__" in register/bit names. e.g., "_PCH_VLV_" + - Registers / bits that are different between SKUs are denoted by "_" + at the end of the register/bit names + - Registers / bits of new devices introduced in a PCH generation will be just named + as "_PCH_" without inserted. + +--*/ +#ifndef _PCH_REGS_LPSS_H_ +#define _PCH_REGS_LPSS_H_ + + +// +// Low Power Input Output (LPSS) Module Registers +// + +// +// LPSS DMAC Modules +// PCI Config Space Registers +// +#define PCI_DEVICE_NUMBER_PCH_LPSS_DMAC0 30 +#define PCI_DEVICE_NUMBER_PCH_LPSS_DMAC1 24 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_DMAC 0 + +#define R_PCH_LPSS_DMAC_DEVVENDID 0x00 // Device ID & Vendor ID +#define B_PCH_LPSS_DMAC_DEVVENDID_DID 0xFFFF0000 // Device ID +#define B_PCH_LPSS_DMAC_DEVVENDID_VID 0x0000FFFF // Vendor ID + +#define R_PCH_LPSS_DMAC_STSCMD 0x04 // Status & Command +#define B_PCH_LPSS_DMAC_STSCMD_RMA BIT29 // RMA +#define B_PCH_LPSS_DMAC_STSCMD_RCA BIT28 // RCA +#define B_PCH_LPSS_DMAC_STSCMD_CAPLIST BIT20 // Capability List +#define B_PCH_LPSS_DMAC_STSCMD_INTRSTS BIT19 // Interrupt Status +#define B_PCH_LPSS_DMAC_STSCMD_INTRDIS BIT10 // Interrupt Disable +#define B_PCH_LPSS_DMAC_STSCMD_SERREN BIT8 // SERR# Enable +#define B_PCH_LPSS_DMAC_STSCMD_BME BIT2 // Bus Master Enable +#define B_PCH_LPSS_DMAC_STSCMD_MSE BIT1 // Memory Space Enable + +#define R_PCH_LPSS_DMAC_REVCC 0x08 // Revision ID & Class Code +#define B_PCH_LPSS_DMAC_REVCC_CC 0xFFFFFF00 // Class Code +#define B_PCH_LPSS_DMAC_REVCC_RID 0x000000FF // Revision ID + +#define R_PCH_LPSS_DMAC_CLHB 0x0C +#define B_PCH_LPSS_DMAC_CLHB_MULFNDEV BIT23 +#define B_PCH_LPSS_DMAC_CLHB_HT 0x007F0000 // Header Type +#define B_PCH_LPSS_DMAC_CLHB_LT 0x0000FF00 // Latency Timer +#define B_PCH_LPSS_DMAC_CLHB_CLS 0x000000FF // Cache Line Size + +#define R_PCH_LPSS_DMAC_BAR 0x10 // BAR +#define B_PCH_LPSS_DMAC_BAR_BA 0xFFFFC000 // Base Address +#define V_PCH_LPSS_DMAC_BAR_SIZE 0x4000 +#define N_PCH_LPSS_DMAC_BAR_ALIGNMENT 14 +#define B_PCH_LPSS_DMAC_BAR_SI 0x00000FF0 // Size Indicator +#define B_PCH_LPSS_DMAC_BAR_PF BIT3 // Prefetchable +#define B_PCH_LPSS_DMAC_BAR_TYPE (BIT2 | BIT1) // Type +#define B_PCH_LPSS_DMAC_BAR_MS BIT0 // Message Space + +#define R_PCH_LPSS_DMAC_BAR1 0x14 // BAR 1 +#define B_PCH_LPSS_DMAC_BAR1_BA 0xFFFFF000 // Base Address +#define B_PCH_LPSS_DMAC_BAR1_SI 0x00000FF0 // Size Indicator +#define B_PCH_LPSS_DMAC_BAR1_PF BIT3 // Prefetchable +#define B_PCH_LPSS_DMAC_BAR1_TYPE (BIT2 | BIT1) // Type +#define B_PCH_LPSS_DMAC_BAR1_MS BIT0 // Message Space + +#define R_PCH_LPSS_DMAC_SSID 0x2C // Sub System ID +#define B_PCH_LPSS_DMAC_SSID_SID 0xFFFF0000 // Sub System ID +#define B_PCH_LPSS_DMAC_SSID_SVID 0x0000FFFF // Sub System Vendor ID + +#define R_PCH_LPSS_DMAC_ERBAR 0x30 // Expansion ROM BAR +#define B_PCH_LPSS_DMAC_ERBAR_BA 0xFFFFFFFF // Expansion ROM Base Address + +#define R_PCH_LPSS_DMAC_CAPPTR 0x34 // Capability Pointer +#define B_PCH_LPSS_DMAC_CAPPTR_CPPWR 0xFF // Capability Pointer Power + +#define R_PCH_LPSS_DMAC_INTR 0x3C // Interrupt +#define B_PCH_LPSS_DMAC_INTR_ML 0xFF000000 // Max Latency +#define B_PCH_LPSS_DMAC_INTR_MG 0x00FF0000 +#define B_PCH_LPSS_DMAC_INTR_IP 0x00000F00 // Interrupt Pin +#define B_PCH_LPSS_DMAC_INTR_IL 0x000000FF // Interrupt Line + +#define R_PCH_LPSS_DMAC_PCAPID 0x80 // Power Capability ID +#define B_PCH_LPSS_DMAC_PCAPID_PS 0xF8000000 // PME Support +#define B_PCH_LPSS_DMAC_PCAPID_VS 0x00070000 // Version +#define B_PCH_LPSS_DMAC_PCAPID_NC 0x0000FF00 // Next Capability +#define B_PCH_LPSS_DMAC_PCAPID_PC 0x000000FF // Power Capability + +#define R_PCH_LPSS_DMAC_PCS 0x84 // PME Control Status +#define B_PCH_LPSS_DMAC_PCS_PMESTS BIT15 // PME Status +#define B_PCH_LPSS_DMAC_PCS_PMEEN BIT8 // PME Enable +#define B_PCH_LPSS_DMAC_PCS_NSS BIT3 // No Soft Reset +#define B_PCH_LPSS_DMAC_PCS_PS (BIT1 | BIT0) // Power State + +#define R_PCH_LPSS_DMAC_MANID 0xF8 // Manufacturer ID +#define B_PCH_LPSS_DMAC_MANID_MANID 0xFFFFFFFF // Manufacturer ID + + +// +// LPSS I2C Module +// PCI Config Space Registers +// +#define PCI_DEVICE_NUMBER_PCH_LPSS_I2C 24 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_I2C0 1 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_I2C1 2 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_I2C2 3 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_I2C3 4 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_I2C4 5 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_I2C5 6 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_I2C6 7 + +#define R_PCH_LPSS_I2C_DEVVENDID 0x00 // Device ID & Vendor ID +#define B_PCH_LPSS_I2C_DEVVENDID_DID 0xFFFF0000 // Device ID +#define B_PCH_LPSS_I2C_DEVVENDID_VID 0x0000FFFF // Vendor ID + +#define R_PCH_LPSS_I2C_STSCMD 0x04 // Status & Command +#define B_PCH_LPSS_I2C_STSCMD_RMA BIT29 // RMA +#define B_PCH_LPSS_I2C_STSCMD_RCA BIT28 // RCA +#define B_PCH_LPSS_I2C_STSCMD_CAPLIST BIT20 // Capability List +#define B_PCH_LPSS_I2C_STSCMD_INTRSTS BIT19 // Interrupt Status +#define B_PCH_LPSS_I2C_STSCMD_INTRDIS BIT10 // Interrupt Disable +#define B_PCH_LPSS_I2C_STSCMD_SERREN BIT8 // SERR# Enable +#define B_PCH_LPSS_I2C_STSCMD_BME BIT2 // Bus Master Enable +#define B_PCH_LPSS_I2C_STSCMD_MSE BIT1 // Memory Space Enable + +#define R_PCH_LPSS_I2C_REVCC 0x08 // Revision ID & Class Code +#define B_PCH_LPSS_I2C_REVCC_CC 0xFFFFFF00 // Class Code +#define B_PCH_LPSS_I2C_REVCC_RID 0x000000FF // Revision ID + +#define R_PCH_LPSS_I2C_CLHB 0x0C +#define B_PCH_LPSS_I2C_CLHB_MULFNDEV BIT23 +#define B_PCH_LPSS_I2C_CLHB_HT 0x007F0000 // Header Type +#define B_PCH_LPSS_I2C_CLHB_LT 0x0000FF00 // Latency Timer +#define B_PCH_LPSS_I2C_CLHB_CLS 0x000000FF // Cache Line Size + +#define R_PCH_LPSS_I2C_BAR 0x10 // BAR +#define B_PCH_LPSS_I2C_BAR_BA 0xFFFFF000 // Base Address +#define V_PCH_LPSS_I2C_BAR_SIZE 0x1000 +#define N_PCH_LPSS_I2C_BAR_ALIGNMENT 12 +#define B_PCH_LPSS_I2C_BAR_SI 0x00000FF0 // Size Indicator +#define B_PCH_LPSS_I2C_BAR_PF BIT3 // Prefetchable +#define B_PCH_LPSS_I2C_BAR_TYPE (BIT2 | BIT1) // Type +#define B_PCH_LPSS_I2C_BAR_MS BIT0 // Message Space + +#define R_PCH_LPSS_I2C_BAR1 0x14 // BAR 1 +#define B_PCH_LPSS_I2C_BAR1_BA 0xFFFFF000 // Base Address +#define B_PCH_LPSS_I2C_BAR1_SI 0x00000FF0 // Size Indicator +#define B_PCH_LPSS_I2C_BAR1_PF BIT3 // Prefetchable +#define B_PCH_LPSS_I2C_BAR1_TYPE (BIT2 | BIT1) // Type +#define B_PCH_LPSS_I2C_BAR1_MS BIT0 // Message Space + +#define R_PCH_LPSS_I2C_SSID 0x2C // Sub System ID +#define B_PCH_LPSS_I2C_SSID_SID 0xFFFF0000 // Sub System ID +#define B_PCH_LPSS_I2C_SSID_SVID 0x0000FFFF // Sub System Vendor ID + +#define R_PCH_LPSS_I2C_ERBAR 0x30 // Expansion ROM BAR +#define B_PCH_LPSS_I2C_ERBAR_BA 0xFFFFFFFF // Expansion ROM Base Address + +#define R_PCH_LPSS_I2C_CAPPTR 0x34 // Capability Pointer +#define B_PCH_LPSS_I2C_CAPPTR_CPPWR 0xFF // Capability Pointer Power + +#define R_PCH_LPSS_I2C_INTR 0x3C // Interrupt +#define B_PCH_LPSS_I2C_INTR_ML 0xFF000000 // Max Latency +#define B_PCH_LPSS_I2C_INTR_MG 0x00FF0000 +#define B_PCH_LPSS_I2C_INTR_IP 0x00000F00 // Interrupt Pin +#define B_PCH_LPSS_I2C_INTR_IL 0x000000FF // Interrupt Line + +#define R_PCH_LPSS_I2C_PCAPID 0x80 // Power Capability ID +#define B_PCH_LPSS_I2C_PCAPID_PS 0xF8000000 // PME Support +#define B_PCH_LPSS_I2C_PCAPID_VS 0x00070000 // Version +#define B_PCH_LPSS_I2C_PCAPID_NC 0x0000FF00 // Next Capability +#define B_PCH_LPSS_I2C_PCAPID_PC 0x000000FF // Power Capability + +#define R_PCH_LPSS_I2C_PCS 0x84 // PME Control Status +#define B_PCH_LPSS_I2C_PCS_PMESTS BIT15 // PME Status +#define B_PCH_LPSS_I2C_PCS_PMEEN BIT8 // PME Enable +#define B_PCH_LPSS_I2C_PCS_NSS BIT3 // No Soft Reset +#define B_PCH_LPSS_I2C_PCS_PS (BIT1 | BIT0) // Power State + +#define R_PCH_LPSS_I2C_MANID 0xF8 // Manufacturer ID +#define B_PCH_LPSS_I2C_MANID_MANID 0xFFFFFFFF // Manufacturer ID + +// +// LPSS I2C Module +// Memory Space Registers +// +#define R_PCH_LPSS_I2C_MEM_RESETS 0x804 // Software Reset +#define B_PCH_LPSS_I2C_MEM_RESETS_FUNC BIT1 // Function Clock Domain Reset +#define B_PCH_LPSS_I2C_MEM_RESETS_APB BIT0 // APB Domain Reset + +// +// LPSS PWM Modules +// PCI Config Space Registers +// +#define PCI_DEVICE_NUMBER_PCH_LPSS_PWM 30 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_PWM0 1 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_PWM1 2 + +#define R_PCH_LPSS_PWM_DEVVENDID 0x00 // Device ID & Vendor ID +#define B_PCH_LPSS_PWM_DEVVENDID_DID 0xFFFF0000 // Device ID +#define B_PCH_LPSS_PWM_DEVVENDID_VID 0x0000FFFF // Vendor ID + +#define R_PCH_LPSS_PWM_STSCMD 0x04 // Status & Command +#define B_PCH_LPSS_PWM_STSCMD_RMA BIT29 // RMA +#define B_PCH_LPSS_PWM_STSCMD_RCA BIT28 // RCA +#define B_PCH_LPSS_PWM_STSCMD_CAPLIST BIT20 // Capability List +#define B_PCH_LPSS_PWM_STSCMD_INTRSTS BIT19 // Interrupt Status +#define B_PCH_LPSS_PWM_STSCMD_INTRDIS BIT10 // Interrupt Disable +#define B_PCH_LPSS_PWM_STSCMD_SERREN BIT8 // SERR# Enable +#define B_PCH_LPSS_PWM_STSCMD_BME BIT2 // Bus Master Enable +#define B_PCH_LPSS_PWM_STSCMD_MSE BIT1 // Memory Space Enable + +#define R_PCH_LPSS_PWM_REVCC 0x08 // Revision ID & Class Code +#define B_PCH_LPSS_PWM_REVCC_CC 0xFFFFFF00 // Class Code +#define B_PCH_LPSS_PWM_REVCC_RID 0x000000FF // Revision ID + +#define R_PCH_LPSS_PWM_CLHB 0x0C +#define B_PCH_LPSS_PWM_CLHB_MULFNDEV BIT23 +#define B_PCH_LPSS_PWM_CLHB_HT 0x007F0000 // Header Type +#define B_PCH_LPSS_PWM_CLHB_LT 0x0000FF00 // Latency Timer +#define B_PCH_LPSS_PWM_CLHB_CLS 0x000000FF // Cache Line Size + +#define R_PCH_LPSS_PWM_BAR 0x10 // BAR +#define B_PCH_LPSS_PWM_BAR_BA 0xFFFFF000 // Base Address +#define V_PCH_LPSS_PWM_BAR_SIZE 0x1000 +#define N_PCH_LPSS_PWM_BAR_ALIGNMENT 12 +#define B_PCH_LPSS_PWM_BAR_SI 0x00000FF0 // Size Indicator +#define B_PCH_LPSS_PWM_BAR_PF BIT3 // Prefetchable +#define B_PCH_LPSS_PWM_BAR_TYPE (BIT2 | BIT1) // Type +#define B_PCH_LPSS_PWM_BAR_MS BIT0 // Message Space + +#define R_PCH_LPSS_PWM_BAR1 0x14 // BAR 1 +#define B_PCH_LPSS_PWM_BAR1_BA 0xFFFFF000 // Base Address +#define B_PCH_LPSS_PWM_BAR1_SI 0x00000FF0 // Size Indicator +#define B_PCH_LPSS_PWM_BAR1_PF BIT3 // Prefetchable +#define B_PCH_LPSS_PWM_BAR1_TYPE (BIT2 | BIT1) // Type +#define B_PCH_LPSS_PWM_BAR1_MS BIT0 // Message Space + +#define R_PCH_LPSS_PWM_SSID 0x2C // Sub System ID +#define B_PCH_LPSS_PWM_SSID_SID 0xFFFF0000 // Sub System ID +#define B_PCH_LPSS_PWM_SSID_SVID 0x0000FFFF // Sub System Vendor ID + +#define R_PCH_LPSS_PWM_ERBAR 0x30 // Expansion ROM BAR +#define B_PCH_LPSS_PWM_ERBAR_BA 0xFFFFFFFF // Expansion ROM Base Address + +#define R_PCH_LPSS_PWM_CAPPTR 0x34 // Capability Pointer +#define B_PCH_LPSS_PWM_CAPPTR_CPPWR 0xFF // Capability Pointer Power + +#define R_PCH_LPSS_PWM_INTR 0x3C // Interrupt +#define B_PCH_LPSS_PWM_INTR_ML 0xFF000000 // Max Latency +#define B_PCH_LPSS_PWM_INTR_MG 0x00FF0000 +#define B_PCH_LPSS_PWM_INTR_IP 0x00000F00 // Interrupt Pin +#define B_PCH_LPSS_PWM_INTR_IL 0x000000FF // Interrupt Line + +#define R_PCH_LPSS_PWM_PCAPID 0x80 // Power Capability ID +#define B_PCH_LPSS_PWM_PCAPID_PS 0xF8000000 // PME Support +#define B_PCH_LPSS_PWM_PCAPID_VS 0x00070000 // Version +#define B_PCH_LPSS_PWM_PCAPID_NC 0x0000FF00 // Next Capability +#define B_PCH_LPSS_PWM_PCAPID_PC 0x000000FF // Power Capability + +#define R_PCH_LPSS_PWM_PCS 0x84 // PME Control Status +#define B_PCH_LPSS_PWM_PCS_PMESTS BIT15 // PME Status +#define B_PCH_LPSS_PWM_PCS_PMEEN BIT8 // PME Enable +#define B_PCH_LPSS_PWM_PCS_NSS BIT3 // No Soft Reset +#define B_PCH_LPSS_PWM_PCS_PS (BIT1 | BIT0) // Power State + +#define R_PCH_LPSS_PWM_MANID 0xF8 // Manufacturer ID +#define B_PCH_LPSS_PWM_MANID_MANID 0xFFFFFFFF // Manufacturer ID + +// +// LPSS PWM Module +// Memory Space Registers +// +#define R_PCH_LPSS_PWM_MEM_RESETS 0x804 // Software Reset +#define B_PCH_LPSS_PWM_MEM_RESETS_FUNC BIT1 // Function Clock Domain Reset +#define B_PCH_LPSS_PWM_MEM_RESETS_APB BIT0 // APB Domain Reset + +// +// LPSS HSUART Modules +// PCI Config Space Registers +// +#define PCI_DEVICE_NUMBER_PCH_LPSS_HSUART 30 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_HSUART0 3 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_HSUART1 4 + +#define R_PCH_LPSS_HSUART_DEVVENDID 0x00 // Device ID & Vendor ID +#define B_PCH_LPSS_HSUART_DEVVENDID_DID 0xFFFF0000 // Device ID +#define B_PCH_LPSS_HSUART_DEVVENDID_VID 0x0000FFFF // Vendor ID + +#define R_PCH_LPSS_HSUART_STSCMD 0x04 // Status & Command +#define B_PCH_LPSS_HSUART_STSCMD_RMA BIT29 // RMA +#define B_PCH_LPSS_HSUART_STSCMD_RCA BIT28 // RCA +#define B_PCH_LPSS_HSUART_STSCMD_CAPLIST BIT20 // Capability List +#define B_PCH_LPSS_HSUART_STSCMD_INTRSTS BIT19 // Interrupt Status +#define B_PCH_LPSS_HSUART_STSCMD_INTRDIS BIT10 // Interrupt Disable +#define B_PCH_LPSS_HSUART_STSCMD_SERREN BIT8 // SERR# Enable +#define B_PCH_LPSS_HSUART_STSCMD_BME BIT2 // Bus Master Enable +#define B_PCH_LPSS_HSUART_STSCMD_MSE BIT1 // Memory Space Enable + +#define R_PCH_LPSS_HSUART_REVCC 0x08 // Revision ID & Class Code +#define B_PCH_LPSS_HSUART_REVCC_CC 0xFFFFFF00 // Class Code +#define B_PCH_LPSS_HSUART_REVCC_RID 0x000000FF // Revision ID + +#define R_PCH_LPSS_HSUART_CLHB 0x0C +#define B_PCH_LPSS_HSUART_CLHB_MULFNDEV BIT23 +#define B_PCH_LPSS_HSUART_CLHB_HT 0x007F0000 // Header Type +#define B_PCH_LPSS_HSUART_CLHB_LT 0x0000FF00 // Latency Timer +#define B_PCH_LPSS_HSUART_CLHB_CLS 0x000000FF // Cache Line Size + +#define R_PCH_LPSS_HSUART_BAR 0x10 // BAR +#define B_PCH_LPSS_HSUART_BAR_BA 0xFFFFF000 // Base Address +#define V_PCH_LPSS_HSUART_BAR_SIZE 0x1000 +#define N_PCH_LPSS_HSUART_BAR_ALIGNMENT 12 +#define B_PCH_LPSS_HSUART_BAR_SI 0x00000FF0 // Size Indicator +#define B_PCH_LPSS_HSUART_BAR_PF BIT3 // Prefetchable +#define B_PCH_LPSS_HSUART_BAR_TYPE (BIT2 | BIT1) // Type +#define B_PCH_LPSS_HSUART_BAR_MS BIT0 // Message Space + +#define R_PCH_LPSS_HSUART_BAR1 0x14 // BAR 1 +#define B_PCH_LPSS_HSUART_BAR1_BA 0xFFFFF000 // Base Address +#define B_PCH_LPSS_HSUART_BAR1_SI 0x00000FF0 // Size Indicator +#define B_PCH_LPSS_HSUART_BAR1_PF BIT3 // Prefetchable +#define B_PCH_LPSS_HSUART_BAR1_TYPE (BIT2 | BIT1) // Type +#define B_PCH_LPSS_HSUART_BAR1_MS BIT0 // Message Space + +#define R_PCH_LPSS_HSUART_SSID 0x2C // Sub System ID +#define B_PCH_LPSS_HSUART_SSID_SID 0xFFFF0000 // Sub System ID +#define B_PCH_LPSS_HSUART_SSID_SVID 0x0000FFFF // Sub System Vendor ID + +#define R_PCH_LPSS_HSUART_ERBAR 0x30 // Expansion ROM BAR +#define B_PCH_LPSS_HSUART_ERBAR_BA 0xFFFFFFFF // Expansion ROM Base Address + +#define R_PCH_LPSS_HSUART_CAPPTR 0x34 // Capability Pointer +#define B_PCH_LPSS_HSUART_CAPPTR_CPPWR 0xFF // Capability Pointer Power + +#define R_PCH_LPSS_HSUART_INTR 0x3C // Interrupt +#define B_PCH_LPSS_HSUART_INTR_ML 0xFF000000 // Max Latency +#define B_PCH_LPSS_HSUART_INTR_MG 0x00FF0000 +#define B_PCH_LPSS_HSUART_INTR_IP 0x00000F00 // Interrupt Pin +#define B_PCH_LPSS_HSUART_INTR_IL 0x000000FF // Interrupt Line + +#define R_PCH_LPSS_HSUART_PCAPID 0x80 // Power Capability ID +#define B_PCH_LPSS_HSUART_PCAPID_PS 0xF8000000 // PME Support +#define B_PCH_LPSS_HSUART_PCAPID_VS 0x00070000 // Version +#define B_PCH_LPSS_HSUART_PCAPID_NC 0x0000FF00 // Next Capability +#define B_PCH_LPSS_HSUART_PCAPID_PC 0x000000FF // Power Capability + +#define R_PCH_LPSS_HSUART_PCS 0x84 // PME Control Status +#define B_PCH_LPSS_HSUART_PCS_PMESTS BIT15 // PME Status +#define B_PCH_LPSS_HSUART_PCS_PMEEN BIT8 // PME Enable +#define B_PCH_LPSS_HSUART_PCS_NSS BIT3 // No Soft Reset +#define B_PCH_LPSS_HSUART_PCS_PS (BIT1 | BIT0) // Power State + +#define R_PCH_LPSS_HSUART_MANID 0xF8 // Manufacturer ID +#define B_PCH_LPSS_HSUART_MANID_MANID 0xFFFFFFFF // Manufacturer ID + +// +// LPSS HSUART Module +// Memory Space Registers +// +#define R_PCH_LPSS_HSUART_MEM_PCP 0x800 // Private Clock Parameters +#define B_PCH_LPSS_HSUART_MEM_PCP_CLKUPDATE BIT31 // Clock Divider Update +#define B_PCH_LPSS_HSUART_MEM_PCP_NVAL 0x7FFF0000 // N value for the M over N divider +#define B_PCH_LPSS_HSUART_MEM_PCP_MVAL 0x0000FFFE // M value for the M over N divider +#define B_PCH_LPSS_HSUART_MEM_PCP_CLKEN BIT0 // Clock Enable + +#define R_PCH_LPSS_HSUART_MEM_RESETS 0x804 // Software Reset +#define B_PCH_LPSS_HSUART_MEM_RESETS_FUNC BIT1 // Function Clock Domain Reset +#define B_PCH_LPSS_HSUART_MEM_RESETS_APB BIT0 // APB Domain Reset + +// +// LPSS SPI Module +// PCI Config Space Registers +// +#define PCI_DEVICE_NUMBER_PCH_LPSS_SPI 30 +#define PCI_FUNCTION_NUMBER_PCH_LPSS_SPI 5 + +#define R_PCH_LPSS_SPI_DEVVENDID 0x00 // Device ID & Vendor ID +#define B_PCH_LPSS_SPI_DEVVENDID_DID 0xFFFF0000 // Device ID +#define B_PCH_LPSS_SPI_DEVVENDID_VID 0x0000FFFF // Vendor ID + +#define R_PCH_LPSS_SPI_STSCMD 0x04 // Status & Command +#define B_PCH_LPSS_SPI_STSCMD_RMA BIT29 // RMA +#define B_PCH_LPSS_SPI_STSCMD_RCA BIT28 // RCA +#define B_PCH_LPSS_SPI_STSCMD_CAPLIST BIT20 // Capability List +#define B_PCH_LPSS_SPI_STSCMD_INTRSTS BIT19 // Interrupt Status +#define B_PCH_LPSS_SPI_STSCMD_INTRDIS BIT10 // Interrupt Disable +#define B_PCH_LPSS_SPI_STSCMD_SERREN BIT8 // SERR# Enable +#define B_PCH_LPSS_SPI_STSCMD_BME BIT2 // Bus Master Enable +#define B_PCH_LPSS_SPI_STSCMD_MSE BIT1 // Memory Space Enable + +#define R_PCH_LPSS_SPI_REVCC 0x08 // Revision ID & Class Code +#define B_PCH_LPSS_SPI_REVCC_CC 0xFFFFFF00 // Class Code +#define B_PCH_LPSS_SPI_REVCC_RID 0x000000FF // Revision ID + +#define R_PCH_LPSS_SPI_CLHB 0x0C +#define B_PCH_LPSS_SPI_CLHB_MULFNDEV BIT23 +#define B_PCH_LPSS_SPI_CLHB_HT 0x007F0000 // Header Type +#define B_PCH_LPSS_SPI_CLHB_LT 0x0000FF00 // Latency Timer +#define B_PCH_LPSS_SPI_CLHB_CLS 0x000000FF // Cache Line Size + +#define R_PCH_LPSS_SPI_BAR 0x10 // BAR +#define B_PCH_LPSS_SPI_BAR_BA 0xFFFFF000 // Base Address +#define V_PCH_LPSS_SPI_BAR_SIZE 0x1000 +#define N_PCH_LPSS_SPI_BAR_ALIGNMENT 12 +#define B_PCH_LPSS_SPI_BAR_SI 0x00000FF0 // Size Indicator +#define B_PCH_LPSS_SPI_BAR_PF BIT3 // Prefetchable +#define B_PCH_LPSS_SPI_BAR_TYPE (BIT2 | BIT1) // Type +#define B_PCH_LPSS_SPI_BAR_MS BIT0 // Message Space + +#define R_PCH_LPSS_SPI_BAR1 0x14 // BAR 1 +#define B_PCH_LPSS_SPI_BAR1_BA 0xFFFFF000 // Base Address +#define B_PCH_LPSS_SPI_BAR1_SI 0x00000FF0 // Size Indicator +#define B_PCH_LPSS_SPI_BAR1_PF BIT3 // Prefetchable +#define B_PCH_LPSS_SPI_BAR1_TYPE (BIT2 | BIT1) // Type +#define B_PCH_LPSS_SPI_BAR1_MS BIT0 // Message Space + +#define R_PCH_LPSS_SPI_SSID 0x2C // Sub System ID +#define B_PCH_LPSS_SPI_SSID_SID 0xFFFF0000 // Sub System ID +#define B_PCH_LPSS_SPI_SSID_SVID 0x0000FFFF // Sub System Vendor ID + +#define R_PCH_LPSS_SPI_ERBAR 0x30 // Expansion ROM BAR +#define B_PCH_LPSS_SPI_ERBAR_BA 0xFFFFFFFF // Expansion ROM Base Address + +#define R_PCH_LPSS_SPI_CAPPTR 0x34 // Capability Pointer +#define B_PCH_LPSS_SPI_CAPPTR_CPPWR 0xFF // Capability Pointer Power + +#define R_PCH_LPSS_SPI_INTR 0x3C // Interrupt +#define B_PCH_LPSS_SPI_INTR_ML 0xFF000000 // Max Latency +#define B_PCH_LPSS_SPI_INTR_MG 0x00FF0000 +#define B_PCH_LPSS_SPI_INTR_IP 0x00000F00 // Interrupt Pin +#define B_PCH_LPSS_SPI_INTR_IL 0x000000FF // Interrupt Line + +#define R_PCH_LPSS_SPI_PCAPID 0x80 // Power Capability ID +#define B_PCH_LPSS_SPI_PCAPID_PS 0xF8000000 // PME Support +#define B_PCH_LPSS_SPI_PCAPID_VS 0x00070000 // Version +#define B_PCH_LPSS_SPI_PCAPID_NC 0x0000FF00 // Next Capability +#define B_PCH_LPSS_SPI_PCAPID_PC 0x000000FF // Power Capability + +#define R_PCH_LPSS_SPI_PCS 0x84 // PME Control Status +#define B_PCH_LPSS_SPI_PCS_PMESTS BIT15 // PME Status +#define B_PCH_LPSS_SPI_PCS_PMEEN BIT8 // PME Enable +#define B_PCH_LPSS_SPI_PCS_NSS BIT3 // No Soft Reset +#define B_PCH_LPSS_SPI_PCS_PS (BIT1 | BIT0) // Power State + +#define R_PCH_LPSS_SPI_MANID 0xF8 // Manufacturer ID +#define B_PCH_LPSS_SPI_MANID_MANID 0xFFFFFFFF // Manufacturer ID + +// +// LPSS SPI Module +// Memory Space Registers +// +#define R_PCH_LPSS_SPI_MEM_PCP 0x400 // Private Clock Parameters +#define B_PCH_LPSS_SPI_MEM_PCP_CLKUPDATE BIT31 // Clock Divider Update +#define B_PCH_LPSS_SPI_MEM_PCP_NVAL 0x7FFF0000 // N value for the M over N divider +#define B_PCH_LPSS_SPI_MEM_PCP_MVAL 0x0000FFFE // M value for the M over N divider +#define B_PCH_LPSS_SPI_MEM_PCP_CLKEN BIT0 // Clock Enable + +#define R_PCH_LPSS_SPI_MEM_RESETS 0x404 // Software Reset +#define B_PCH_LPSS_SPI_MEM_RESETS_FUNC BIT1 // Function Clock Domain Reset +#define B_PCH_LPSS_SPI_MEM_RESETS_APB BIT0 // APB Domain Reset + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsPcie.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsPcie.h new file mode 100644 index 0000000000..bb50709182 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsPcie.h @@ -0,0 +1,89 @@ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchRegsPcie.h + + @brief + Register names for VLV PCI-E root port devices + + Conventions: + + - Prefixes: + 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 + - In general, PCH registers are denoted by "_PCH_" in register names + - Registers / bits that are different between PCH generations are denoted by + "_PCH__" in register/bit names. e.g., "_PCH_VLV_" + - Registers / bits that are different between SKUs are denoted by "_" + at the end of the register/bit names + - Registers / bits of new devices introduced in a PCH generation will be just named + as "_PCH_" without inserted. + +--*/ +#ifndef _PCH_REGS_PCIE_H_ +#define _PCH_REGS_PCIE_H_ + +#define PCH_PCIE_MAX_ROOT_PORTS 4 + +/// +/// VLV PCI Express Root Ports (D28:F0~F3) +/// +#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS 28 +#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 0 +#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2 1 +#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3 2 +#define PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4 3 + +#define R_PCH_PCIE_ID 0x00 // Identifiers +#define B_PCH_PCIE_ID_DID 0xFFFF0000 // Device ID +#define V_PCH_PCIE_DEVICE_ID_0 0x0F48 // PCIE Root Port #1 +#define V_PCH_PCIE_DEVICE_ID_1 0x0F4A // PCIE Root Port #2 +#define V_PCH_PCIE_DEVICE_ID_2 0x0F4C // PCIE Root Port #3 +#define V_PCH_PCIE_DEVICE_ID_3 0x0F4E // PCIE Root Port #4 +#define B_PCH_PCIE_ID_VID 0x0000FFFF // Vendor ID +#define V_PCH_PCIE_VENDOR_ID V_PCH_INTEL_VENDOR_ID + + +#define R_PCH_PCIE_BNUM_SLT 0x18 // Bus Numbers; Secondary Latency Timer +#define B_PCH_PCIE_BNUM_SLT_SLT 0xFF000000 // Secondary Latency Timer +#define B_PCH_PCIE_BNUM_SLT_SBBN 0x00FF0000 // Subordinate Bus Number +#define B_PCH_PCIE_BNUM_SLT_SCBN 0x0000FF00 // Secondary Bus Number +#define B_PCH_PCIE_BNUM_SLT_PBN 0x000000FF // Primary Bus Number +#define R_PCH_PCIE_CAPP 0x34 // Capabilities List Pointer +#define B_PCH_PCIE_CAPP 0xFF // Capabilities Pointer + +#define R_PCH_PCIE_SLCTL_SLSTS 0x58 // Slot Control; Slot Status +#define S_PCH_PCIE_SLCTL_SLSTS 4 +#define B_PCH_PCIE_SLCTL_SLSTS_DLLSC BIT24 // Data Link Layer State Changed +#define B_PCH_PCIE_SLCTL_SLSTS_PDS BIT22 // Presence Detect State +#define B_PCH_PCIE_SLCTL_SLSTS_MS BIT21 // MRL Sensor State +#define B_PCH_PCIE_SLCTL_SLSTS_PDC BIT19 // Presence Detect Changed +#define B_PCH_PCIE_SLCTL_SLSTS_MSC BIT18 // MRL Sensor Changed +#define B_PCH_PCIE_SLCTL_SLSTS_PFD BIT17 // Power Fault Detected +#define B_PCH_PCIE_SLCTL_SLSTS_DLLSCE BIT12 // Data Link Layer State Changed Enable +#define B_PCH_PCIE_SLCTL_SLSTS_PCC BIT10 // Power Controller Control +#define B_PCH_PCIE_SLCTL_SLSTS_HPE BIT5 // Hot Plug Interrupt Enable +#define B_PCH_PCIE_SLCTL_SLSTS_CCE BIT4 // Command Completed Interrupt Enable +#define B_PCH_PCIE_SLCTL_SLSTS_PDE BIT3 // Presence Detect Changed Enable + +#define R_PCH_PCIE_SVID 0x94 // Subsystem Vendor IDs +#define S_PCH_PCIE_SVID 4 +#define B_PCH_PCIE_SVID_SID 0xFFFF0000 // Subsystem Identifier +#define B_PCH_PCIE_SVID_SVID 0x0000FFFF // Subsystem Vendor Identifier + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsPcu.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsPcu.h new file mode 100644 index 0000000000..29629890c0 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsPcu.h @@ -0,0 +1,1205 @@ +/*++ + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PchRegsPcu.h + +Abstract: + + Register names for VLV PCU device. + + Conventions: + + - Prefixes: + 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 + - In general, PCH registers are denoted by "_PCH_" in register names + - Registers / bits that are different between PCH generations are denoted by + "_PCH__" in register/bit names. e.g., "_PCH_VLV_" + - Registers / bits that are different between SKUs are denoted by "_" + at the end of the register/bit names + - Registers / bits of new devices introduced in a PCH generation will be just named + as "_PCH_" without inserted. + +--*/ +#ifndef _PCH_REGS_LPC_H_ +#define _PCH_REGS_LPC_H_ + +// +// VLV PCU Registers (D31:F0) +// +#define PCI_DEVICE_NUMBER_PCH_LPC 31 +#define PCI_FUNCTION_NUMBER_PCH_LPC 0 + +// Silicon Steppings +typedef enum { + PchA0 = 0, + PchA1 = 1, + PchB0 = 2, + PchB1 = 3, + PchB2 = 4, + PchB3 = 5, + PchC0 = 6, + PchD0 = 7, + PchSteppingMax +} PCH_STEPPING; + +#define R_PCH_LPC_REG_ID 0x00 // Identifiers Register +#define B_PCH_LPC_DEVICE_ID 0xFFFF0000 // Device Identification +#define B_PCH_LPC_VENDOR_ID 0x0000FFFF // Vendor Identification +#define V_PCH_LPC_VENDOR_ID V_PCH_INTEL_VENDOR_ID // Vendor ID for Intel +// +// General VLV PCU Device ID +// +#define V_PCH_LPC_DEVICE_ID_0 0x0F1C +#define V_PCH_LPC_DEVICE_ID_1 0x0F1D +#define V_PCH_LPC_DEVICE_ID_2 0x0F1E +#define V_PCH_LPC_DEVICE_ID_3 0x0F1F + +#define R_PCH_LPC_COMMAND 0x04 // Command +#define B_PCH_LPC_COMMAND_ID BIT10 // Interrupt Disable +#define B_PCH_LPC_COMMAND_FBE BIT9 // Fast Back to Back Enable +#define B_PCH_LPC_COMMAND_SERR_EN BIT8 // SERR# Enable +#define B_PCH_LPC_COMMAND_WCC BIT7 // Wait Cycle Control +#define B_PCH_LPC_COMMAND_PER BIT6 // Parity Error Response Enable +#define B_PCH_LPC_COMMAND_VPS BIT5 // VGA Palette Snoop +#define B_PCH_LPC_COMMAND_MWIE BIT4 // Memory Write and Invalidate Enable +#define B_PCH_LPC_COMMAND_SCE BIT3 // Special Cycle Enable +#define B_PCH_LPC_COMMAND_BME BIT2 // Bus Master Enable +#define B_PCH_LPC_COMMAND_MSE BIT1 // Memory Space Enable +#define B_PCH_LPC_COMMAND_IOSE BIT0 // I/O Space Enable + +#define R_PCH_LPC_DEV_STS 0x06 // Status +#define B_PCH_LPC_DEV_STS_DPE BIT15 // Detected Parity Error +#define B_PCH_LPC_DEV_STS_SSE BIT14 // Signaled System Error +#define B_PCH_LPC_DEV_STS_RMA BIT13 // Received Master Abort +#define B_PCH_LPC_DEV_STS_RTA BIT12 // Received Target Abort +#define B_PCH_LPC_DEV_STS_STA BIT11 // Signaled Target Abort +#define B_PCH_LPC_DEV_STS_DEVT_STS (BIT10 | BIT9) // DEVSEL# Timing Status +#define B_PCH_LPC_DEV_STS_MDPED BIT8 // Data Parity Error +#define B_PCH_LPC_DEV_STS_FB2B BIT7 // Fast Back to Back Capable +#define B_PCH_LPC_DEV_STS_66MHZ_CAP BIT5 // 66 MHz capable +#define B_PCH_LPC_DEV_STS_CAP_LIST BIT4 // Capabilities List +#define B_PCH_LPC_DEV_STS_INT_STS BIT3 // Interrupt Status + +#define R_PCH_LPC_RID_CC 0x08 // Revision ID & Class Code +#define B_PCH_LPC_RID_CC_BCC 0xFF000000 // Base Class Code +#define B_PCH_LPC_RID_CC_SCC 0x00FF0000 // Sub-Class Code +#define B_PCH_LPC_RID_CC_PI 0x0000FF00 // Programming Interface +#define B_PCH_LPC_RID_CC_RID 0x000000FF // Revision ID + +// Silicon Steppings + +#define V_PCH_LPC_RID_0 0x01 // A0 Stepping (17 x 17) +#define V_PCH_LPC_RID_1 0x02 // A0 Stepping (25 x 27) +#define V_PCH_LPC_RID_2 0x03 // A1 Stepping (17 x 17) +#define V_PCH_LPC_RID_3 0x04 // A1 Stepping (25 x 27) +#define V_PCH_LPC_RID_4 0x05 // B0 Stepping (17 x 17) +#define V_PCH_LPC_RID_5 0x06 // B0 Stepping (25 x 27) +#define V_PCH_LPC_RID_6 0x07 // B1 Stepping (17 x 17) +#define V_PCH_LPC_RID_7 0x08 // B1 Stepping (25 x 27) +#define V_PCH_LPC_RID_8 0x09 // B2 Stepping (17 x 17) +#define V_PCH_LPC_RID_9 0x0A // B2 Stepping (25 x 27) +#define V_PCH_LPC_RID_A 0x0B // B3 Stepping (17 x 17) +#define V_PCH_LPC_RID_B 0x0C // B3 Stepping (25 x 27) +#define V_PCH_LPC_RID_C 0x0D // C0 Stepping (17 x 17) +#define V_PCH_LPC_RID_D 0x0E // C0 Stepping (25 x 27) + +#define R_PCH_LPC_MLT 0x0D // Master Latency Timer +#define B_PCH_LPC_MLT_MLC 0xF8 // Master Latency Count + +#define R_PCH_LPC_HEADTYP 0x0E // Header Type +#define B_PCH_LPC_HEADTYP_MFD BIT7 // Multi-function Device +#define B_PCH_LPC_HEADTYP_HT 0x7F // Header Type + +#define R_PCH_LPC_SS 0x2C // Subsystem ID & Vendor ID +#define B_PCH_LPC_SS_SSID 0xFFFF0000 // Subsystem ID +#define B_PCH_LPC_SS_SSVID 0x0000FFFF // Subsystem Vendor ID + +#define R_PCH_LPC_CAP_LIST 0x34 // Capability List +#define B_PCH_LPC_CAP_LIST_CP 0xFF // Capability Pointer + +#define R_PCH_LPC_ACPI_BASE 0x40 // ABASE, 16bit +#define B_PCH_LPC_ACPI_BASE_BAR 0x0000FF80 // Base Address, 128 Bytes +#define B_PCH_LPC_ACPI_BASE_EN BIT1 // Enable Bit +#define B_PCH_LPC_ACPI_BASE_MEMI BIT0 // Memory Space Indication + +#define R_PCH_LPC_PMC_BASE 0x44 // PBASE, 32bit, 512 Bytes +#define B_PCH_LPC_PMC_BASE_BAR 0xFFFFFE00 // Base Address +#define B_PCH_LPC_PMC_BASE_PREF BIT3 // Prefetchable +#define B_PCH_LPC_PMC_BASE_ADDRNG BIT2 // Address Range +#define B_PCH_LPC_PMC_BASE_EN BIT1 // Enable Bit +#define B_PCH_LPC_PMC_BASE_MEMI BIT0 // Memory Space Indication + +#define R_PCH_LPC_GPIO_BASE 0x48 // GBASE, 16bit +#define B_PCH_LPC_GPIO_BASE_BAR 0xFF00 // Base Address, 256 Bytes +#define B_PCH_LPC_GPIO_BASE_EN BIT1 // Enable Bit +#define B_PCH_LPC_GPIO_BASE_MEMI BIT0 // Memory Space Indication + +#define R_PCH_LPC_IO_BASE 0x4C // IOBASE, 32bit +#define B_PCH_LPC_IO_BASE_BAR 0xFFFFC000 // Base Address, 16 KiloBytes +#define B_PCH_LPC_IO_BASE_PREF BIT3 // Prefetchable +#define B_PCH_LPC_IO_BASE_ADDRNG BIT2 // Address Range +#define B_PCH_LPC_IO_BASE_EN BIT1 // Enable Bit +#define B_PCH_LPC_IO_BASE_MEMI BIT0 // Memory Space Indication + +#define R_PCH_LPC_ILB_BASE 0x50 // IBASE, 32bit +#define B_PCH_LPC_ILB_BASE_BAR 0xFFFFFE00 // Base Address, 512 bytes +#define B_PCH_LPC_ILB_BASE_PREF BIT3 // Prefetchable +#define B_PCH_LPC_ILB_BASE_ADDRNG BIT2 // Address Range +#define B_PCH_LPC_ILB_BASE_EN BIT1 // Enable Bit +#define B_PCH_LPC_ILB_BASE_MEMI BIT0 // Memory Space Indication + +#define R_PCH_LPC_SPI_BASE 0x54 // SBASE, 32bit +#define B_PCH_LPC_SPI_BASE_BAR 0xFFFFFE00 // Base Address, 512 bytes +#define B_PCH_LPC_SPI_BASE_PREF BIT3 // Prefetchable +#define B_PCH_LPC_SPI_BASE_ADDRNG BIT2 // Address Range +#define B_PCH_LPC_SPI_BASE_EN BIT1 // Enable Bit +#define B_PCH_LPC_SPI_BASE_MEMI BIT0 // Memory Space Indicator + +#define R_PCH_LPC_MPHY_BASE 0x58 // MPBASE, 32bit +#define B_PCH_LPC_MPHY_BASE_BAR 0xFFF00000 // Base Address, 1 MegaByte +#define B_PCH_LPC_MPHY_BASE_PREF BIT3 // Prefetchable +#define B_PCH_LPC_MPHY_BASE_ADDRNG BIT2 // Address Range +#define B_PCH_LPC_MPHY_BASE_EN BIT1 // Enable Bit +#define B_PCH_LPC_MPHY_BASE_MEMI BIT0 // Memory Space Indicator + +#define R_PCH_LPC_PUNIT_BASE 0x5C // PUBASE, 32bit +#define B_PCH_LPC_PUNIT_BASE_BAR 0xFFFFF800 // Base Address, 2K bytes +#define B_PCH_LPC_PUNIT_BASE_PREF BIT3 // Prefetchable +#define B_PCH_LPC_PUNIT_BASE_ADDRNG BIT2 // Address Range +#define B_PCH_LPC_PUNIT_BASE_EN BIT1 // Enable Bit +#define B_PCH_LPC_PUNIT_BASE_MEMI BIT0 // Memory Space Indicator + +#define R_PCH_LPC_UART_CTRL 0x80 // UART Control +#define B_PCH_LPC_UART_CTRL_COM1_EN BIT0 // COM1 Enable + +#define R_PCH_LPC_FWH_BIOS_DEC 0xD8 // BIOS Decode Enable +#define B_PCH_LPC_FWH_BIOS_DEC_EF8 BIT15 // F8-FF Enable +#define B_PCH_LPC_FWH_BIOS_DEC_EF0 BIT14 // F0-F8 Enable +#define B_PCH_LPC_FWH_BIOS_DEC_EE8 BIT13 // E8-EF Enable +#define B_PCH_LPC_FWH_BIOS_DEC_EE0 BIT12 // E0-E8 Enable +#define B_PCH_LPC_FWH_BIOS_DEC_ED8 BIT11 // D8-DF Enable +#define B_PCH_LPC_FWH_BIOS_DEC_ED0 BIT10 // D0-D8 Enable +#define B_PCH_LPC_FWH_BIOS_DEC_EC8 BIT9 // C8-CF Enable +#define B_PCH_LPC_FWH_BIOS_DEC_EC0 BIT8 // C0-C8 Enable +#define B_PCH_LPC_FWH_BIOS_DEC_LFE BIT7 // Legacy F Segment Enable +#define B_PCH_LPC_FWH_BIOS_DEC_LEE BIT6 // Legacy E Segment Enable +#define B_PCH_LPC_FWH_BIOS_DEC_E70 BIT3 // 70-7F Enable +#define B_PCH_LPC_FWH_BIOS_DEC_E60 BIT2 // 60-6F Enable +#define B_PCH_LPC_FWH_BIOS_DEC_E50 BIT1 // 50-5F Enable +#define B_PCH_LPC_FWH_BIOS_DEC_E40 BIT0 // 40-4F Enable + +#define R_PCH_LPC_FDCAP 0xE0 // Feature Detection Capability ID +#define B_PCH_LPC_FDCAP_NEXT 0xFF00 // Next Capability +#define B_PCH_LPC_FDCAP_CAPID 0x00FF // Capability ID + +#define R_PCH_LPC_FDLEN 0xE2 // Feature Detection Capability Length +#define B_PCH_LPC_FDLEN_CAPLEN 0xFF // Capability Length + +#define R_PCH_LPC_FDVER 0xE3 // Feature Detection Capability Version +#define B_PCH_LPC_FDVER_VSCID 0xF0 // Vendor Specific Capability ID +#define B_PCH_LPC_FDVER_CAPVER 0x0F // Capability Version + +#define R_PCH_LPC_FVECTIDX 0xE4 // Feature Vector Index + +#define R_PCH_LPC_FVECTD 0xE8 // Feature Vector Data + +#define R_PCH_LPC_RCBA 0xF0 // RCBA, 32bit +#define B_PCH_LPC_RCBA_BAR 0xFFFFFC00 // Base Address, 1 KiloByte +#define B_PCH_LPC_RCBA_EN BIT0 // Enable Bit + +#define R_PCH_LPC_ULT_OBS 0xF4 // ULT Observability +#define B_PCH_LPC_ULT_OBS_WNUM 0x3FF000 // Reserved Wafer Number +#define B_PCH_LPC_ULT_OBS_XLOC 0xFC0 // Reserved X Loc +#define B_PCH_LPC_ULT_OBS_YLOC 0x3F // Reserved Y Loc + +#define R_PCH_LPC_MAN_ID 0xF8 // Manufacturer ID +#define B_PCH_LPC_MAN_ID_DPID 0xF000000 // Dot Portion of Process ID +#define B_PCH_LPC_MAN_ID_MSID 0xFF0000 // Manufacturing Stepping Identifier +#define B_PCH_LPC_MAN_ID_MID 0xFF00 // Manufacturing Identifier +#define B_PCH_LPC_MAN_ID_PPID 0xFF // Process Portion of Process ID + +#define R_PCH_LPC_CGC 0xFC // Clock Gating Control +#define B_PCH_LPC_CGC_SBLCG BIT9 // IOSF-SB Local Clock Gating Disable +#define B_PCH_LPC_CGC_SBTCG BIT8 // IOSF-SB Trunk Clock Gating (Request) Disable +#define B_PCH_LPC_CGC_PRILCG BIT1 // IOSF-PRI Local Clock Gating Disable +#define B_PCH_LPC_CGC_PRITCG BIT0 // IOSF-PRI Trunk Clock Gating (Request) Disable + +// +// iLB Memory Space Registers (IBASE) +// +#define R_PCH_ILB_ACPI_CNT 0x00 // ACPI Control +#define B_PCH_ILB_ACPI_CNT_SCI_IRQ_SEL (BIT2 | BIT1 | BIT0) // SCI IRQ Select +#define V_PCH_ILB_ACPI_CNT_SCI_IRQ_9 0 // IRQ9 +#define V_PCH_ILB_ACPI_CNT_SCI_IRQ_10 BIT0 // IRQ10 +#define V_PCH_ILB_ACPI_CNT_SCI_IRQ_11 BIT1 // IRQ11 +#define V_PCH_ILB_ACPI_CNT_SCI_IRQ_20 BIT2 // IRQ20 (Only if APIC enabled) +#define V_PCH_ILB_ACPI_CNT_SCI_IRQ_21 (BIT2 | BIT0) // IRQ21 (Only if APIC enabled) +#define V_PCH_ILB_ACPI_CNT_SCI_IRQ_22 (BIT2 | BIT1) // IRQ22 (Only if APIC enabled) +#define V_PCH_ILB_ACPI_CNT_SCI_IRQ_23 (BIT2 | BIT1 | BIT0) // IRQ23 (Only if APIC enabled) + +#define R_PCH_ILB_MC 0x04 // Miscellaneous Control +#define B_PCH_ILB_MC_DRTC BIT3 // Disable RTC +#define B_PCH_ILB_MC_D8259 BIT2 // Disable 8259 +#define B_PCH_ILB_MC_D8254 BIT1 // Disable 8254 +#define B_PCH_ILB_MC_AME BIT0 // Alternate Access Mode Enable + +#define R_PCH_ILB_PIRQA_ROUT 0x08 // PIRQA Routing Control +#define R_PCH_ILB_PIRQB_ROUT 0x09 // PIRQB Routing Control +#define R_PCH_ILB_PIRQC_ROUT 0x0A // PIRQC Routing Control +#define R_PCH_ILB_PIRQD_ROUT 0x0B // PIRQD Routing Control +#define R_PCH_ILB_PIRQE_ROUT 0x0C // PIRQE Routing Control +#define R_PCH_ILB_PIRQF_ROUT 0x0D // PIRQF Routing Control +#define R_PCH_ILB_PIRQG_ROUT 0x0E // PIRQG Routing Control +#define R_PCH_ILB_PIRQH_ROUT 0x0F // PIRQH Routing Control +// +// Bit values are the same for R_PCH_ILB_PIRQA_ROUT to R_PCH_ILB_PIRQH_ROUT +// +#define B_PCH_ILB_PIRQX_ROUT_IRQEN BIT7 // Interrupt Routing Enable +#define B_PCH_ILB_PIRQX_ROUT 0x0F // IRQ Routing +#define V_PCH_ILB_PIRQX_ROUT_IRQ_3 0x03 // Route to IRQ3 +#define V_PCH_ILB_PIRQX_ROUT_IRQ_4 0x04 // Route to IRQ4 +#define V_PCH_ILB_PIRQX_ROUT_IRQ_5 0x05 // Route to IRQ5 +#define V_PCH_ILB_PIRQX_ROUT_IRQ_6 0x06 // Route to IRQ6 +#define V_PCH_ILB_PIRQX_ROUT_IRQ_7 0x07 // Route to IRQ7 +#define V_PCH_ILB_PIRQX_ROUT_IRQ_9 0x09 // Route to IRQ9 +#define V_PCH_ILB_PIRQX_ROUT_IRQ_10 0x0A // Route to IRQ10 +#define V_PCH_ILB_PIRQX_ROUT_IRQ_11 0x0B // Route to IRQ11 +#define V_PCH_ILB_PIRQX_ROUT_IRQ_12 0x0C // Route to IRQ12 +#define V_PCH_ILB_PIRQX_ROUT_IRQ_14 0x0E // Route to IRQ14 +#define V_PCH_ILB_PIRQX_ROUT_IRQ_15 0x0F // Route to IRQ15 + +#define R_PCH_ILB_SERIRQ_CNT 0x10 // Serial IRQ Control +#define B_PCH_ILB_SERIRQ_CNT_SIRQMD BIT7 // Mode + +#define R_PCH_ILB_ULKMC 0x14 // USB Legacy Keyboard / Mouse Control +#define B_PCH_ILB_ULKMC_TRAPBY64W BIT11 // SMI Caused by Port 64 Write +#define B_PCH_ILB_ULKMC_TRAPBY64R BIT10 // SMI Caused by Port 64 Read +#define B_PCH_ILB_ULKMC_TRAPBY60W BIT9 // SMI Caused by Port 60 Write +#define B_PCH_ILB_ULKMC_TRAPBY60R BIT8 // SMI Caused by Port 60 Read +#define B_PCH_ILB_ULKMC_64WEN BIT3 // SMI on Port 64 Writes Enable +#define B_PCH_ILB_ULKMC_64REN BIT2 // SMI on Port 64 Reads Enable +#define B_PCH_ILB_ULKMC_60WEN BIT1 // SMI on Port 60 Writes Enable +#define B_PCH_ILB_ULKMC_60REN BIT0 // SMI on Port 60 Reads Enable + +#define R_PCH_ILB_FWH_BIOS_SEL 0x18 // FWH ID Select +#define B_PCH_ILB_FWH_BIOS_SEL_F8 0xF0000000 // F8-FF ID Select +#define B_PCH_ILB_FWH_BIOS_SEL_F0 0x0F000000 // F0-F7 ID Select +#define B_PCH_ILB_FWH_BIOS_SEL_E8 0x00F00000 // E8-EF ID Select +#define B_PCH_ILB_FWH_BIOS_SEL_E0 0x000F0000 // E0-E7 ID Select +#define B_PCH_ILB_FWH_BIOS_SEL_D8 0x0000F000 // D8-DF ID Select +#define B_PCH_ILB_FWH_BIOS_SEL_D0 0x00000F00 // D0-D7 ID Select +#define B_PCH_ILB_FWH_BIOS_SEL_C8 0x000000F0 // C8-CF ID Select +#define B_PCH_ILB_FWH_BIOS_SEL_C0 0x0000000F // C0-C7 ID Select + +#define R_PCH_ILB_BIOS_CNTL 0x1C // BIOS Control +#define S_PCH_ILB_BIOS_CNTL 4 +#define B_PCH_ILB_BIOS_CNTL_PFE BIT8 // Prefetch Enable +#define B_PCH_ILB_BIOS_CNTL_LE BIT1 // Lock Enable +#define N_PCH_ILB_BIOS_CNTL_LE 1 +#define B_PCH_ILB_BIOS_CNTL_WP BIT0 // Write Protect + +#define R_PCH_ILB_D0IR 0x20 // Device 0 Interrupt Route +#define R_PCH_ILB_D1IR 0x22 // Device 1 Interrupt Route +#define R_PCH_ILB_D2IR 0x24 // Device 2 Interrupt Route +#define R_PCH_ILB_D3IR 0x26 // Device 3 Interrupt Route +#define R_PCH_ILB_D4IR 0x28 // Device 4 Interrupt Route +#define R_PCH_ILB_D5IR 0x2A // Device 5 Interrupt Route +#define R_PCH_ILB_D6IR 0x2C // Device 6 Interrupt Route +#define R_PCH_ILB_D7IR 0x2E // Device 7 Interrupt Route +#define R_PCH_ILB_D8IR 0x30 // Device 8 Interrupt Route +#define R_PCH_ILB_D9IR 0x32 // Device 9 Interrupt Route +#define R_PCH_ILB_D10IR 0x34 // Device 10 Interrupt Route +#define R_PCH_ILB_D11IR 0x36 // Device 11 Interrupt Route +#define R_PCH_ILB_D12IR 0x38 // Device 12 Interrupt Route +#define R_PCH_ILB_D13IR 0x3A // Device 13 Interrupt Route +#define R_PCH_ILB_D14IR 0x3C // Device 14 Interrupt Route +#define R_PCH_ILB_D15IR 0x3E // Device 15 Interrupt Route +#define R_PCH_ILB_D16IR 0x40 // Device 16 Interrupt Route +#define R_PCH_ILB_D17IR 0x42 // Device 17 Interrupt Route +#define R_PCH_ILB_D18IR 0x44 // Device 18 Interrupt Route +#define R_PCH_ILB_D19IR 0x46 // Device 19 Interrupt Route +#define R_PCH_ILB_D20IR 0x48 // Device 20 Interrupt Route +#define R_PCH_ILB_D21IR 0x4A // Device 21 Interrupt Route +#define R_PCH_ILB_D22IR 0x4C // Device 22 Interrupt Route +#define R_PCH_ILB_D23IR 0x4E // Device 23 Interrupt Route +#define R_PCH_ILB_D24IR 0x50 // Device 24 Interrupt Route +#define R_PCH_ILB_D25IR 0x52 // Device 25 Interrupt Route +#define R_PCH_ILB_D26IR 0x54 // Device 26 Interrupt Route +#define R_PCH_ILB_D27IR 0x56 // Device 27 Interrupt Route +#define R_PCH_ILB_D28IR 0x58 // Device 28 Interrupt Route +#define R_PCH_ILB_D29IR 0x5A // Device 29 Interrupt Route +#define R_PCH_ILB_D30IR 0x5C // Device 30 Interrupt Route +#define R_PCH_ILB_D31IR 0x5E // Device 31 Interrupt Route + +#define B_PCH_ILB_DXXIR_IDR_MASK (BIT14 | BIT13 | BIT12) // INTD Mask +#define V_PCH_ILB_DXXIR_IDR_PIRQA 0 // INTD Mapping to IRQ A +#define V_PCH_ILB_DXXIR_IDR_PIRQB BIT12 // INTD Mapping to IRQ B +#define V_PCH_ILB_DXXIR_IDR_PIRQC BIT13 // INTD Mapping to IRQ C +#define V_PCH_ILB_DXXIR_IDR_PIRQD (BIT13 | BIT12) // INTD Mapping to IRQ D +#define V_PCH_ILB_DXXIR_IDR_PIRQE BIT14 // INTD Mapping to IRQ E +#define V_PCH_ILB_DXXIR_IDR_PIRQF (BIT14 | BIT12) // INTD Mapping to IRQ F +#define V_PCH_ILB_DXXIR_IDR_PIRQG (BIT14 | BIT13) // INTD Mapping to IRQ G +#define V_PCH_ILB_DXXIR_IDR_PIRQH (BIT14 | BIT13 | BIT12) // INTD Mapping to IRQ H + +#define B_PCH_ILB_DXXIR_ICR_MASK (BIT10 | BIT9 | BIT8) // INTC Mask +#define V_PCH_ILB_DXXIR_ICR_PIRQA 0 // INTC Mapping to IRQ A +#define V_PCH_ILB_DXXIR_ICR_PIRQB BIT8 // INTC Mapping to IRQ B +#define V_PCH_ILB_DXXIR_ICR_PIRQC BIT9 // INTC Mapping to IRQ C +#define V_PCH_ILB_DXXIR_ICR_PIRQD (BIT9 | BIT8) // INTC Mapping to IRQ D +#define V_PCH_ILB_DXXIR_ICR_PIRQE BIT10 // INTC Mapping to IRQ E +#define V_PCH_ILB_DXXIR_ICR_PIRQF (BIT10 | BIT8) // INTC Mapping to IRQ F +#define V_PCH_ILB_DXXIR_ICR_PIRQG (BIT10 | BIT9) // INTC Mapping to IRQ G +#define V_PCH_ILB_DXXIR_ICR_PIRQH (BIT10 | BIT9 | BIT8) // INTC Mapping to IRQ H + +#define B_PCH_ILB_DXXIR_IBR_MASK (BIT6 | BIT5 | BIT4) // INTB Mask +#define V_PCH_ILB_DXXIR_IBR_PIRQA 0 // INTB Mapping to IRQ A +#define V_PCH_ILB_DXXIR_IBR_PIRQB BIT4 // INTB Mapping to IRQ B +#define V_PCH_ILB_DXXIR_IBR_PIRQC BIT5 // INTB Mapping to IRQ C +#define V_PCH_ILB_DXXIR_IBR_PIRQD (BIT5 | BIT4) // INTB Mapping to IRQ D +#define V_PCH_ILB_DXXIR_IBR_PIRQE BIT6 // INTB Mapping to IRQ E +#define V_PCH_ILB_DXXIR_IBR_PIRQF (BIT6 | BIT4) // INTB Mapping to IRQ F +#define V_PCH_ILB_DXXIR_IBR_PIRQG (BIT6 | BIT5) // INTB Mapping to IRQ G +#define V_PCH_ILB_DXXIR_IBR_PIRQH (BIT6 | BIT5 | BIT4) // INTB Mapping to IRQ H + +#define B_PCH_ILB_DXXIR_IAR_MASK (BIT2 | BIT1 | BIT0) // INTA Mask +#define V_PCH_ILB_DXXIR_IAR_PIRQA 0 // INTA Mapping to IRQ A +#define V_PCH_ILB_DXXIR_IAR_PIRQB BIT0 // INTA Mapping to IRQ B +#define V_PCH_ILB_DXXIR_IAR_PIRQC BIT1 // INTA Mapping to IRQ C +#define V_PCH_ILB_DXXIR_IAR_PIRQD (BIT1 | BIT0) // INTA Mapping to IRQ D +#define V_PCH_ILB_DXXIR_IAR_PIRQE BIT2 // INTA Mapping to IRQ E +#define V_PCH_ILB_DXXIR_IAR_PIRQF (BIT2 | BIT0) // INTA Mapping to IRQ F +#define V_PCH_ILB_DXXIR_IAR_PIRQG (BIT2 | BIT1) // INTA Mapping to IRQ G +#define V_PCH_ILB_DXXIR_IAR_PIRQH (BIT2 | BIT1 | BIT0) // INTA Mapping to IRQ H + +#define R_PCH_ILB_OIC 0x60 // Other Interrupt Controller +#define B_PCH_ILB_OIC_SIRQEN BIT12 // Serial IRQ Enable +#define B_PCH_ILB_OIC_AEN BIT8 // APIC Enable + +#define R_PCH_ILB_RTC_CONF 0x64 // RTC Control +#define B_PCH_ILB_RTC_CONF_UCMOS_LOCK BIT1 // Upper 128 Byte Lock +#define B_PCH_ILB_RTC_CONF_LCMOS_LOCK BIT0 // Lower 128 Byte Lock + +#define R_PCH_ILB_RTM 0x68 // RTC Test Mode +#define B_PCH_ILB_RTM_RTM1 (BIT2 | BIT1 | BIT0) + +#define R_PCH_ILB_BCS 0x6C // BIOS Control Status +#define B_PCH_ILB_BCS_SMIWPEN BIT1 // SMI WPD Enable +#define B_PCH_ILB_BCS_SMIWPST BIT0 // SMI WPD Status + +#define R_PCH_ILB_LE 0x70 // LE +#define B_PCH_ILB_LE_IRQ12C BIT1 // IRQ12 Cause +#define B_PCH_ILB_LE_IRQ1C BIT0 // IRQ1 Cause + +#define R_PCH_ILB_RTCC 0x74 // RTC HIP Configuration +#define B_PCH_ILB_RTCC_RTCB4 BIT6 // RTC Bias Resistor 4, Adds 480 Kohm +#define B_PCH_ILB_RTCC_RTCB3 BIT5 // RTC Bias Resistor 3, Adds 240 Kohm +#define B_PCH_ILB_RTCC_RTCB2 BIT4 // RTC Bias Resistor 2, Adds 120 Kohm +#define B_PCH_ILB_RTCC_RTCB1 BIT3 // RTC Bias Resistor 1, Adds 60 Kohm +#define B_PCH_ILB_RTCC_RTCB0 BIT2 // RTC Bias Resistor 0, Adds 30 Kohm +#define B_PCH_ILB_RTCC_DSWEN BIT1 // Deep Sleep Well Enable +#define B_PCH_ILB_RTCC_FEN BIT0 // Enable the Fast Oscillator Bypass Mode + +#define R_PCH_ILB_DEF0 0x78 // Defeature Register 0 +#define B_PCH_ILB_DEF0_SHRTSYNC BIT22 // Short Sync Abort Defeature +#define B_PCH_ILB_DEF0_SDD BIT21 // Sub Decode Disable + +#define R_PCH_ILB_DEF1 0x7C // Defeature Register 1 +#define B_PCH_ILB_DEF1_TPMPF BIT10 // usb2leg_chknbit_TPM_PF +#define B_PCH_ILB_DEF1_HPETDEF BIT8 // usb2leg_chknbit_hpet +#define B_PCH_ILB_DEF1_ECWS BIT6 // 8254 Early CW Select +#define B_PCH_ILB_DEF1_FOF BIT5 // 8254 Freeze on first on 1st rd wr11 +#define B_PCH_ILB_DEF1_FOAR BIT4 // 8254 Freeze_On_AnyRead +#define B_PCH_ILB_DEF1_LMOO BIT3 // 8259 L2L0_Match_On_OCW2 +#define B_PCH_ILB_DEF1_DFP BIT2 // 8259 Disable_Freeze_Priority +#define B_PCH_ILB_DEF1_EETI BIT1 // 8259 Extend_EdgeTrig_IRQ +#define B_PCH_ILB_DEF1_DSAEOI BIT0 // 8259 Disable_Slave_AEOI + +#define R_PCH_ILB_GNMI 0x80 // NMI Register +#define S_PCH_ILB_GNMI 4 +#define B_PCH_ILB_GNMI_NMI2SMIEN BIT6 // NMI to SMI Enable +#define N_PCH_ILB_GNMI_NMI2SMIEN 6 +#define B_PCH_ILB_GNMI_NMI2SMIST BIT5 // NMI to SMI Status +#define N_PCH_ILB_GNMI_NMI2SMIST 5 +#define B_PCH_ILB_GNMI_NMIN BIT4 // NMI NOW +#define B_PCH_ILB_GNMI_NMINS BIT3 // NMI NOW Status +#define B_PCH_ILB_GNMI_GNMIED BIT2 // GPIO NMI Edge Detection +#define B_PCH_ILB_GNMI_GNMIE BIT1 // GPIO NMI Enable +#define B_PCH_ILB_GNMI_GNMIS BIT0 // GPIO NMI Status + +#define R_PCH_ILB_LPCC 0x84 // LPC Control +#define B_PCH_ILB_LPCC_LPCCLK_SLC BIT8 // iLPCCLK Mux Select +#define B_PCH_ILB_LPCC_LPCCLK_FORCE_OFF BIT3 +#define B_PCH_ILB_LPCC_CLKRUN_EN BIT2 // LPC CLKRUN Protocol Enable +#define B_PCH_ILB_LPCC_LPCCLK1EN BIT1 // Clock 1 Enable +#define B_PCH_ILB_LPCC_LPCCLK0EN BIT0 // Clock 0 Enable + +#define R_PCH_ILB_IRQE 0x88 // IRQ Enable Control +#define B_PCH_ILB_IRQE_IRQ4TO7EN (BIT7 | BIT6 | BIT5 | BIT4) // IRQ4 - IRQ7 Enable +#define B_PCH_ILB_IRQE_UARTIRQEN_IRQ3 BIT3 // UART IRQ3 Enable + +// +// ACPI and Legacy I/O Registers (ABASE) +// +#define R_PCH_ACPI_PM1_STS 0x00 // Power Management 1 Status +#define S_PCH_ACPI_PM1_STS 2 +#define B_PCH_ACPI_PM1_STS_WAK BIT15 // Wake Status +#define B_PCH_ACPI_PM1_STS_WAK_PCIE0 BIT14 // PCI Express 0 Wake Status +#define B_PCH_ACPI_PM1_STS_USB_CLKLESS BIT13 // USB Clockless Status +#define B_PCH_ACPI_PM1_STS_PRBTNOR BIT11 // Power Button Override Status +#define B_PCH_ACPI_PM1_STS_RTC BIT10 // RTC Status +#define B_PCH_ACPI_PM1_STS_PWRBTN BIT8 // Power Button Status +#define B_PCH_ACPI_PM1_STS_GBL BIT5 // Global Status +#define B_PCH_ACPI_PM1_STS_WAK_PCIE3 BIT4 // PCI Express 3 Wake Status +#define B_PCH_ACPI_PM1_STS_WAK_PCIE2 BIT3 // PCI Express 2 Wake Status +#define B_PCH_ACPI_PM1_STS_WAK_PCIE1 BIT2 // PCI Express 1 Wake Status +#define B_PCH_ACPI_PM1_STS_TMROF BIT0 // Timer Overflow Status +#define N_PCH_ACPI_PM1_STS_WAK 15 +#define N_PCH_ACPI_PM1_STS_PRBTNOR 11 +#define N_PCH_ACPI_PM1_STS_RTC 10 +#define N_PCH_ACPI_PM1_STS_PWRBTN 8 +#define N_PCH_ACPI_PM1_STS_GBL 5 +#define N_PCH_ACPI_PM1_STS_TMROF 0 + +#define R_PCH_ACPI_PM1_EN 0x02 // Power Management 1 Enables +#define S_PCH_ACPI_PM1_EN 2 +#define B_PCH_ACPI_PM1_WAK_DIS_PCIE0 BIT14 // PCI Express 0 Disable +#define B_PCH_ACPI_PM1_EN_USB_CLKLESS BIT13 // USB Clockless Enable Bit +#define B_PCH_ACPI_PM1_EN_RTC BIT10 // RTC Alarm Enable Bit +#define B_PCH_ACPI_PM1_EN_PWRBTN BIT8 // Power Button Enable Bit +#define B_PCH_ACPI_PM1_EN_GBL BIT5 // Global Enable Bit +#define B_PCH_ACPI_PM1_WAK_DIS_PCIE3 BIT4 // PCI Express 3 Disable +#define B_PCH_ACPI_PM1_WAK_DIS_PCIE2 BIT3 // PCI Express 2 Disable +#define B_PCH_ACPI_PM1_WAK_DIS_PCIE1 BIT2 // PCI Express 1 Disable +#define B_PCH_ACPI_PM1_EN_TMROF BIT0 // Timer Overflow Interrupt Enable Bit +#define N_PCH_ACPI_PM1_EN_RTC 10 +#define N_PCH_ACPI_PM1_EN_PWRBTN 8 +#define N_PCH_ACPI_PM1_EN_GBL 5 +#define N_PCH_ACPI_PM1_EN_TMROF 0 + +#define R_PCH_ACPI_PM1_CNT 0x04 // Power Management 1 Control +#define S_PCH_ACPI_PM1_CNT 4 +#define B_PCH_ACPI_PM1_CNT_SLP_EN BIT13 // Sleep enable +#define B_PCH_ACPI_PM1_CNT_SLP_TYP (BIT12 | BIT11 | BIT10) // Sleep Type +#define V_PCH_ACPI_PM1_CNT_S0 0x00000000 // ON (S0) +#define V_PCH_ACPI_PM1_CNT_S1 0x00000400 // Puts CPU in S1 state (S1) +#define V_PCH_ACPI_PM1_CNT_S3 0x00001400 // Suspend-to-RAM (S3) +#define V_PCH_ACPI_PM1_CNT_S4 0x00001800 // Suspend-to-Disk (S4) +#define V_PCH_ACPI_PM1_CNT_S5 0x00001C00 // Soft Off (S5) +#define B_PCH_ACPI_PM1_CNT_GBL_RLS BIT2 +#define B_PCH_ACPI_PM1_CNT_BM_RLD BIT1 // Treated as Scratchpad Bit +#define B_PCH_ACPI_PM1_CNT_SCI_EN BIT0 // SCI Enable + +#define R_PCH_ACPI_PM1_TMR 0x08 // Power Management 1 Timer +#define B_PCH_ACPI_PM1_TMR_VAL 0xFFFFFF // The timer value mask +#define V_PCH_ACPI_PM1_TMR_MAX_VAL 0x1000000 // The timer is 24 bit overflow +#define V_PCH_ACPI_PM1_TMR_FREQUENCY 3579545 // Timer Frequency +#define V_PCH_ACPI_PM1_TMR_NUM_BITS 24 // Programmed to 24 not 32 +#define V_PCH_ACPI_PM1_TMR_MAX_BITS 32 + +#define R_PCH_ACPI_GPE0a_STS 0x20 // General Purpose Event 0a Status +#define S_PCH_ACPI_GPE0a_STS 4 +#define B_PCH_ACPI_GPE0a_STS_CORE_GPIO 0xFF000000 // CORE GPIO Status +#define B_PCH_ACPI_GPE0a_STS_SUS_GPIO 0x00FF0000 // SUS GPIO Status +#define B_PCH_ACPI_GPE0a_STS_PME_B0 BIT13 // Power Management Event Bus 0 Status +#define B_PCH_ACPI_GPE0a_STS_BATLOW BIT10 // Battery Low Status +#define B_PCH_ACPI_GPE0a_STS_PCI_EXP BIT9 // PCI Express Status +#define B_PCH_ACPI_GPE0a_STS_GUNIT_SCI BIT5 // GUNIT SCI Status +#define B_PCH_ACPI_GPE0a_STS_PUNIT_SCI BIT4 // PUNIT SCI Status +#define B_PCH_ACPI_GPE0a_STS_SWGPE BIT2 // Software GPE Status +#define B_PCH_ACPI_GPE0a_STS_HOT_PLUG BIT1 // Hot Plug Status +#define N_PCH_ACPI_GPE0a_STS_PME_B0 13 +#define N_PCH_ACPI_GPE0a_STS_BATLOW 10 +#define N_PCH_ACPI_GPE0a_STS_PCI_EXP 9 +#define N_PCH_ACPI_GPE0a_STS_GUNIT_SCI 5 +#define N_PCH_ACPI_GPE0a_STS_PUNIT_SCI 4 +#define N_PCH_ACPI_GPE0a_STS_SWGPE 2 +#define N_PCH_ACPI_GPE0a_STS_HOT_PLUG 1 + +#define R_PCH_ACPI_GPE0a_EN 0x28 // General Purpose Event 0a Enables +#define S_PCH_ACPI_GPE0a_EN 4 +#define B_PCH_ACPI_GPE0a_EN_CORE_GPIO 0xFF000000 // CORE GPIO Enable +#define B_PCH_ACPI_GPE0a_EN_SUS_GPIO 0x00FF0000 // SUS GPIO Enable +#define B_PCH_ACPI_GPE0a_EN_PME_B0 BIT13 // Power Management Event Bus 0 Enable +#define B_PCH_ACPI_GPE0a_EN_BATLOW BIT10 // Battery Low Enable +#define B_PCH_ACPI_GPE0a_EN_PCI_EXP BIT9 // PCI Express Enable +#define B_PCH_ACPI_GPE0a_EN_SWGPE BIT2 // Software GPE Enable +#define B_PCH_ACPI_GPE0a_EN_HOT_PLUG BIT1 // Hot Plug Enable +#define N_PCH_ACPI_GPE0a_EN_PME_B0 13 +#define N_PCH_ACPI_GPE0a_EN_BATLOW 10 +#define N_PCH_ACPI_GPE0a_EN_PCI_EXP 9 +#define N_PCH_ACPI_GPE0a_EN_SWGPE 2 +#define N_PCH_ACPI_GPE0a_EN_HOT_PLUG 1 + +#define R_PCH_SMI_EN 0x30 // SMI Control and Enable +#define S_PCH_SMI_EN 4 +#define B_PCH_SMI_EN_LEGACY_USB3 BIT31 // Legacy USB 3 Enable +#define B_PCH_SMI_EN_INTEL_USB2 BIT18 // Intel USB 2 Enable +#define B_PCH_SMI_EN_LEGACY_USB2 BIT17 // Legacy USB 2 Enable +#define B_PCH_SMI_EN_PERIODIC BIT14 // Periodic Enable +#define B_PCH_SMI_EN_TCO BIT13 // TCO Enable +#define B_PCH_SMI_EN_BIOS_RLS BIT7 // BIOS RLS +#define B_PCH_SMI_EN_SWSMI_TMR BIT6 // Software SMI Timer Enable +#define B_PCH_SMI_EN_APMC BIT5 // APMC Enable +#define B_PCH_SMI_EN_ON_SLP_EN BIT4 // SMI On Sleep Enable +#define B_PCH_SMI_EN_BIOS BIT2 // BIOS Enable +#define B_PCH_SMI_EN_EOS BIT1 // End of SMI +#define B_PCH_SMI_EN_GBL_SMI BIT0 // Global SMI Enable +#define N_PCH_SMI_EN_LEGACY_USB3 31 +#define N_PCH_SMI_EN_GPIO_UNLOCK 27 +#define N_PCH_SMI_EN_INTEL_USB2 18 +#define N_PCH_SMI_EN_LEGACY_USB2 17 +#define N_PCH_SMI_EN_PERIODIC 14 +#define N_PCH_SMI_EN_TCO 13 +#define N_PCH_SMI_EN_BIOS_RLS 7 +#define N_PCH_SMI_EN_SWSMI_TMR 6 +#define N_PCH_SMI_EN_APMC 5 +#define N_PCH_SMI_EN_ON_SLP_EN 4 +#define N_PCH_SMI_EN_BIOS 2 +#define N_PCH_SMI_EN_EOS 1 +#define N_PCH_SMI_EN_GBL_SMI 0 + +#define R_PCH_SMI_STS 0x34 // SMI Status Register +#define S_PCH_SMI_STS 4 +#define B_PCH_SMI_STS_LEGACY_USB3 BIT31 // Legacy USB 3 Status +#define B_PCH_SMI_STS_GUNIT_SMI BIT29 // GUNIT SMI Status +#define B_PCH_SMI_STS_PUNIT_SMI BIT28 // PUNIT SMI Status +#define B_PCH_SMI_STS_SPI BIT26 // SPI SMI Status +#define B_PCH_SMI_STS_PCI_EXP BIT20 // PCI Express SMI Status +#define B_PCH_SMI_STS_INTEL_USB2 BIT18 // Intel USB 2 Status +#define B_PCH_SMI_STS_LEGACY_USB2 BIT17 // Legacy USB 2 Status +#define N_PCH_SMI_STS_TCO 13 +#define B_PCH_SMI_STS_SMBUS BIT16 // SMBUS SMI Status +#define B_PCH_SMI_STS_ILB BIT15 // ILB SMI Status +#define B_PCH_SMI_STS_PERIODIC BIT14 // Periodic Status +#define B_PCH_SMI_STS_TCO BIT13 // TCO Status +#define B_PCH_SMI_STS_GPE0 BIT9 // GPE0 Status +#define B_PCH_SMI_STS_PM1_STS_REG BIT8 // PM1 Status Register +#define B_PCH_SMI_STS_SWSMI_TMR BIT6 // Software SMI Timer Status +#define B_PCH_SMI_STS_APM BIT5 // APM Status +#define B_PCH_SMI_STS_ON_SLP_EN BIT4 // SMI On Sleep Enable Status +#define B_PCH_SMI_STS_BIOS BIT2 // BIOS Status +#define N_PCH_SMI_STS_LEGACY_USB3 31 +#define N_PCH_SMI_STS_SPI 26 +#define N_PCH_SMI_STS_PCI_EXP 20 +#define N_PCH_SMI_STS_INTEL_USB2 18 +#define N_PCH_SMI_STS_LEGACY_USB2 17 +#define N_PCH_SMI_STS_SMBUS 16 +#define N_PCH_SMI_STS_ILB 15 +#define N_PCH_SMI_STS_PERIODIC 14 +#define N_PCH_SMI_STS_TCO 13 +#define N_PCH_SMI_STS_GPE0 9 +#define N_PCH_SMI_STS_PM1_STS_REG 8 +#define N_PCH_SMI_STS_SWSMI_TMR 6 +#define N_PCH_SMI_STS_APM 5 +#define N_PCH_SMI_STS_ON_SLP_EN 4 +#define N_PCH_SMI_STS_BIOS 2 + +#define R_PCH_ALT_GP_SMI_EN 0x38 // Alternate GPI SMI Enable +#define S_PCH_ALT_GP_SMI_EN 2 +#define B_PCH_ALT_GP_SMI_EN_CORE_GPIO 0xFF00 // SUS GPIO SMI Enable +#define B_PCH_ALT_GP_SMI_EN_SUS_GPIO 0x00FF // CORE GPIO SMI Enable + +#define R_PCH_ALT_GP_SMI_STS 0x3A // Alternate GPI SMI Status +#define S_PCH_ALT_GP_SMI_STS 2 +#define B_PCH_ALT_GP_SMI_STS_CORE_GPIO 0xFF00 // SUS GPIO SMI Status +#define B_PCH_ALT_GP_SMI_STS_SUS_GPIO 0x00FF // CORE GPIO SMI Status + +#define R_PCH_UPRWC 0x3C // USB Per-Port Registers Write Control +#define S_PCH_UPRWC 2 +#define B_PCH_UPRWC_WR_EN_SMI_STS BIT8 // Write Enable Status +#define B_PCH_UPRWC_WR_EN BIT1 // USB Per-Port Registers Write Enable +#define B_PCH_UPRWC_WR_EN_SMI_EN BIT0 // Write Enable SMI Enable + +#define R_PCH_ACPI_GPE_CNTL 0x40 // General Purpose Event Control +#define B_PCH_ACPI_GPE_CNTL_SWGPE_CTRL BIT17 // Software GPE Control +#define B_PCH_ACPI_GPE_CNTL_PCIE3_SCI_EN BIT3 +#define B_PCH_ACPI_GPE_CNTL_PCIE2_SCI_EN BIT2 +#define B_PCH_ACPI_GPE_CNTL_PCIE1_SCI_EN BIT1 +#define B_PCH_ACPI_GPE_CNTL_PCIE0_SCI_EN BIT0 + +#define R_PCH_ACPI_PM2_CNT 0x50 // PM2a Control Block +#define B_PCH_ACPI_PM2_CNT_ARB_DIS BIT0 // Scratchpad Bit + +#define R_PCH_TCO_RLD 0x60 // TCO Reload +#define B_PCH_TCO_RLD_VAL 0x3FF // TCO Timer Count Value + +#define R_PCH_TCO_STS 0x64 // TCO Timer Status +#define S_PCH_TCO_STS 4 +#define B_PCH_TCO_STS_SECOND_TO BIT17 // Second Timeout Status +#define B_PCH_TCO_STS_TIMEOUT BIT3 // Timeout +#define N_PCH_TCO_STS_TIMEOUT 3 + +#define R_PCH_TCO_CNT 0x68 // TCO Control +#define S_PCH_TCO_CNT 2 +#define B_PCH_TCO_CNT_OS_POLICY (BIT21 | BIT20) // OS Policy +#define B_PCH_TCO_CNT_LOCK BIT12 // TCO Enable Lock +#define B_PCH_TCO_CNT_TMR_HLT BIT11 // TCO Timer Halt + +#define R_PCH_TCO_TMR 0x70 // TCO Timer +#define B_PCH_TCO_TMR_TCO_TRLD 0x3FF0000 + +// +// PMC Memory Space Registers (PBASE) +// +#define R_PCH_PMC_PRSTS 0x00 // Power and Reset Status +#define B_PCH_PMC_PRSTS_PRODID 0xFF000000 // Power Management Controller Product ID +#define B_PCH_PMC_PRSTS_REVID 0x00FF0000 // Power Management Controller Revision ID +#define B_PCH_PMC_PRSTS_PM_WD_TMR BIT15 // PMC Watchdog Timer Status +#define B_PCH_PMC_PRSTS_CODE_COPIED_STS BIT11 // Patch Copied Over Status +#define B_PCH_PMC_PRSTS_CODE_LOAD_TO BIT9 // Patch Load Timeout Status +#define B_PCH_PMC_PRSTS_OP_STS BIT8 // PMC Operational Status +#define B_PCH_PMC_PRSTS_SEC_GBLRST_STS BIT7 // SEC Global Reset Status +#define B_PCH_PMC_PRSTS_SEC_WD_TMR_STS BIT6 // SEC Watchdog Timer Status +#define B_PCH_PMC_PRSTS_WOL_OVR_WK_STS BIT5 // Wake On LAN Override Wake Status +#define B_PCH_PMC_PRSTS_HOST_WAKE_STS BIT4 // PMC Host Wake Status + +#define R_PCH_PMC_PM_CFG 0x08 // Power Management Configuration +#define B_PCH_PMC_PM_CFG_SPS BIT5 // Shutdown Policy Select +#define B_PCH_PMC_PM_CFG_NO_REBOOT BIT4 // No Reboot Strap +#define B_PCH_PMC_PM_CFG_SX_ENT_TO_EN BIT3 // S1 / 3 / 4 / 5 Entry Timeout Enable +#define B_PCH_PMC_PM_CFG_TIMING_T581 (BIT1 | BIT0) // Timing t581 + +#define R_PCH_PMC_PM_STS 0x0C // Power Management Status +#define B_PCH_PMC_PM_STS_PMC_MSG_FULL BIT24 // PMC Message Full Status +#define B_PCH_PMC_PM_STS_PMC_MSG_4_FULL BIT23 // PMC 4 Message Full Status +#define B_PCH_PMC_PM_STS_PMC_MSG_3_FULL BIT22 // PMC 3 Message Full Status +#define B_PCH_PMC_PM_STS_PMC_MSG_2_FULL BIT21 // PMC 2 Message Full Status +#define B_PCH_PMC_PM_STS_PMC_MSG_1_FULL BIT20 // PMC 1 Message Full Status +#define B_PCH_PMC_PM_STS_CODE_REQ BIT8 // Patch Request Status +#define B_PCH_PMC_PM_STS_HPR_ENT_TO BIT2 // Host partition Reset Entry Timeout Status +#define B_PCH_PMC_PM_STS_SX_ENT_TO BIT1 // S3 / 4 / 5 Entry Timeout Status + +#define R_PCH_PMC_MTPMC 0x10 // Message to PMC + +#define R_PCH_PMC_GEN_PMCON_1 0x20 // General PM Configuration 1 +#define B_PCH_PMC_GEN_PMCON_UART_EN BIT24 // UART Debug Port Enable +#define B_PCH_PMC_GEN_PMCON_DRAM_INIT BIT23 // DRAM Initialization Scratchpad Bit +#define B_PCH_PMC_GEN_PMCON_MEM_SR BIT21 // Memory Placed in Self-Refresh +#define B_PCH_PMC_GEN_PMCON_SRS BIT20 // System Reset Status +#define B_PCH_PMC_GEN_PMCON_CTS BIT19 // CPU Thermal Trip Status +#define B_PCH_PMC_GEN_PMCON_MIN_SLP_S4 BIT18 // Minimum SLP_S4# Assertion Width Violation Status +#define B_PCH_PMC_GEN_PMCON_PWROK_FLR BIT16 // PWROK Failure +#define B_PCH_PMC_GEN_PMCON_PME_B0_S5_DIS BIT15 // PME B0 S5 Disable +#define B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR BIT14 // SUS Well Power Failure +#define B_PCH_PMC_GEN_PMCON_WOL_ENABLE_OVERRIDE BIT13 // WOL Enable Override +#define B_PCH_PMC_GEN_PMCON_DISABLE_SX_STRETCH BIT12 // Disable SLP_X Scretching After SUS Well Power Up +#define B_PCH_PMC_GEN_PMCON_SLP_S3_MAW (BIT11 | BIT10) // SLP_S3# Minimum Assertion Width +#define V_PCH_PMC_GEN_PMCON_SLP_S3_MAW_60US 0x000 // 60 micro seconds +#define V_PCH_PMC_GEN_PMCON_SLP_S3_MAW_1MS 0x400 // 1 milli second +#define V_PCH_PMC_GEN_PMCON_SLP_S3_MAW_50MS 0x800 // 50 milli seconds +#define V_PCH_PMC_GEN_PMCON_SLP_S3_MAW_2S 0xC00 // 2 seconds +#define B_PCH_PMC_GEN_PMCON_GEN_RST_STS BIT9 // General Reset Status +#define B_PCH_PMC_GEN_PMCON_RTC_RESERVED BIT8 // RTC Reserved +#define B_PCH_PMC_GEN_PMCON_SWSMI_RTSL (BIT7 | BIT6) // SWSMI Rate Select +#define V_PCH_PMC_GEN_PMCON_SWSMI_RTSL_64MS 0xC0 // 64ms +/- 4ms +#define V_PCH_PMC_GEN_PMCON_SWSMI_RTSL_32MS 0x80 // 32ms +/- 4ms +#define V_PCH_PMC_GEN_PMCON_SWSMI_RTSL_16MS 0x40 // 16ms +/- 4ms +#define V_PCH_PMC_GEN_PMCON_SWSMI_RTSL_1_5MS 0x00 // 1.5ms +/- 0.6ms +#define B_PCH_PMC_GEN_PMCON_SLP_S4_MAW (BIT5 | BIT4) // SLP_S4# Minimum Assertion Width +#define V_PCH_PMC_GEN_PMCON_SLP_S4_MAW_1S 0x30 // 1 second +#define V_PCH_PMC_GEN_PMCON_SLP_S4_MAW_2S 0x20 // 2 seconds +#define V_PCH_PMC_GEN_PMCON_SLP_S4_MAW_3S 0x10 // 3 seconds +#define V_PCH_PMC_GEN_PMCON_SLP_S4_MAW_4S 0x00 // 4 seconds +#define B_PCH_PMC_GEN_PMCON_SLP_S4_ASE BIT3 // SLP_S4# Assertion Scretch Enable +#define B_PCH_PMC_GEN_PMCON_RTC_PWR_STS BIT2 // RTC Power Status +#define B_PCH_PMC_GEN_PMCON_AFTERG3_EN BIT0 // After G3 State Enable + +#define R_PCH_PMC_GEN_PMCON_2 0x24 // General PM Configuration 2 +#define B_PCH_PMC_GEN_PMCON_LOCK_S4_STRET_LD BIT18 // SLP_S3 / SLP_S4 Stretching Policy Lock-Down +#define B_PCH_PMC_GEN_PMCON_BIOS_PCI_EXP_EN BIT10 // BIOS PCI Express Enable +#define B_PCH_PMC_GEN_PMCON_PWRBTN_LVL BIT9 // Power Button Level +#define B_PCH_PMC_GEN_PMCON_SMI_LOCK BIT4 // SMI Lock +#define B_PCH_PMC_GEN_PMCON_PER_SMI_SEL (BIT1 | BIT0) // Period SMI Select +#define V_PCH_PMC_GEN_PMCON_PER_SMI_64S 0x0000 // 64 seconds +#define V_PCH_PMC_GEN_PMCON_PER_SMI_32S 0x0001 // 32 seconds +#define V_PCH_PMC_GEN_PMCON_PER_SMI_16S 0x0002 // 16 seconds +#define V_PCH_PMC_GEN_PMCON_PER_SMI_8S 0x0003 // 8 seconds + +#define R_PCH_PMC_MFPMC 0x28 // Message from PMC + +#define R_PCH_PMC_SEC_STS 0x2C // SEC Status +#define B_PCH_PMC_SEC_STS_SEC (BIT3 | BIT2 | BIT1 | BIT0) // SEC Exclusion Cause + +#define R_PCH_PMC_CRID 0x30 // Configured Revision ID +#define B_PCH_PMC_CRID_RID_SEL (BIT1 | BIT0) // Revision ID Select + +#define R_PCH_PMC_FUNC_DIS 0x34 // Function Disable Register +#define B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7 BIT31 // LPSS2 I2C #7 +#define B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6 BIT30 // LPSS2 I2C #6 +#define B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5 BIT29 // LPSS2 I2C #5 +#define B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4 BIT28 // LPSS2 I2C #4 +#define B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3 BIT27 // LPSS2 I2C #3 +#define B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2 BIT26 // LPSS2 I2C #2 +#define B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1 BIT25 // LPSS2 I2C #1 +#define B_PCH_PMC_FUNC_DIS_LPSS2_FUNC0 BIT24 // LPSS2 DMA Disable +#define B_PCH_PMC_FUNC_DIS_PCI_EX_FUNC3 BIT23 // PCI Express Function 3 Disable +#define B_PCH_PMC_FUNC_DIS_PCI_EX_FUNC2 BIT22 // PCI Express Function 2 Disable +#define B_PCH_PMC_FUNC_DIS_PCI_EX_FUNC1 BIT21 // PCI Express Function 1 Disable +#define B_PCH_PMC_FUNC_DIS_PCI_EX_FUNC0 BIT20 // PCI Express Function 0 Disable +#define N_PCH_PMC_FUNC_DIS_PCI_EX_FUNC0 20 +#define B_PCH_PMC_FUNC_DIS_SEC BIT19 // SEC Disable +#define B_PCH_PMC_FUNC_DIS_USB BIT18 // USB Disable +#define B_PCH_PMC_FUNC_DIS_SATA BIT17 // SATA Disable +#define B_PCH_PMC_FUNC_DIS_USH BIT15 // USH (USB3) Disable +#define B_PCH_PMC_FUNC_DIS_OTG BIT14 // USB OTG Disable +#define B_PCH_PMC_FUNC_DIS_LPE BIT13 // LPE Disable +#define B_PCH_PMC_FUNC_DIS_AZALIA BIT12 // Azalia Disable +#define B_PCH_PMC_FUNC_DIS_MIPI BIT11 // MIPI-HSI Disable +#define B_PCH_PMC_FUNC_DIS_SDIO4 BIT11 // SCC SDIO #4 (Device 23, eMMC4.5) Disable +#define B_PCH_PMC_FUNC_DIS_SDIO3 BIT10 // SCC SDIO #3 (Device 18, SD Card) Disable +#define B_PCH_PMC_FUNC_DIS_SDIO2 BIT9 // SCC SDIO #2 (Device 17, SDIO) Disable +#define B_PCH_PMC_FUNC_DIS_SDIO1 BIT8 // SCC SDIO #1 (Device 16, eMMC) Disable +#define B_PCH_PMC_FUNC_DIS_LPSS1_FUNC7 BIT7 // LPSS1 Spare #2 Disable +#define B_PCH_PMC_FUNC_DIS_LPSS1_FUNC6 BIT6 // LPSS1 Spare #1 Disable +#define B_PCH_PMC_FUNC_DIS_LPSS1_FUNC5 BIT5 // LPSS1 SPI Disable +#define B_PCH_PMC_FUNC_DIS_LPSS1_FUNC4 BIT4 // LPSS1 HS-UART #2 Disable +#define B_PCH_PMC_FUNC_DIS_LPSS1_FUNC3 BIT3 // LPSS1 HS-UART #1 Disable +#define B_PCH_PMC_FUNC_DIS_LPSS1_FUNC2 BIT2 // LPSS1 PWM #2 Disable +#define B_PCH_PMC_FUNC_DIS_LPSS1_FUNC1 BIT1 // LPSS1 PWM #1 Disable +#define B_PCH_PMC_FUNC_DIS_LPSS1_FUNC0 BIT0 // LPSS1 DMA Disable + +#define R_PCH_PMC_FUNC_DIS2 0x38 // Function Disable 2 Register +#define B_PCH_PMC_FUNC_DIS2_USH_SS_PHY BIT2 // USH Super Speed PHY Disable +#define B_PCH_PMC_FUNC_DIS2_OTG_SS_PHY BIT1 // OTG Super Speed PHY Disable +#define B_PCH_PMC_FUNC_DIS2_SMBUS BIT0 // SMBus Disable + +#define R_PCH_PMC_PMIR 0x48 // Extended Test Mode Register (ETR) +#define B_PCH_PMC_PMIR_CF9LOCK BIT31 // CF9h Lockdown +#define B_PCH_PMC_PMIR_LTR_DEF BIT22 // LTR Default +#define B_PCH_PMC_PMIR_IGNORE_HPET BIT21 // Ignore HPET Disable Check Before Going to S0i2 +#define B_PCH_PMC_PMIR_CF9GR BIT20 // CF9h Global Reset + +#define R_PCH_PMC_VLT 0x50 // Voltage Detect Register +#define B_PCH_PMC_VLT_FUSES 0xFF // Voltage Detect Fuses + +#define R_PCH_PMC_GPI_ROUT 0x58 // GPI Rout +#define B_PCH_PMC_GPI_ROUT_0 (BIT1 | BIT0) +#define B_PCH_PMC_GPI_ROUT_1 (BIT3 | BIT2) +#define B_PCH_PMC_GPI_ROUT_2 (BIT5 | BIT4) +#define B_PCH_PMC_GPI_ROUT_3 (BIT7 | BIT6) +#define B_PCH_PMC_GPI_ROUT_4 (BIT9 | BIT8) +#define B_PCH_PMC_GPI_ROUT_5 (BIT11 | BIT10) +#define B_PCH_PMC_GPI_ROUT_6 (BIT13 | BIT12) +#define B_PCH_PMC_GPI_ROUT_7 (BIT15 | BIT14) +#define B_PCH_PMC_GPI_ROUT_8 (BIT17 | BIT16) +#define B_PCH_PMC_GPI_ROUT_9 (BIT19 | BIT18) +#define B_PCH_PMC_GPI_ROUT_10 (BIT21 | BIT20) +#define B_PCH_PMC_GPI_ROUT_11 (BIT23 | BIT22) +#define B_PCH_PMC_GPI_ROUT_12 (BIT25 | BIT24) +#define B_PCH_PMC_GPI_ROUT_13 (BIT27 | BIT26) +#define B_PCH_PMC_GPI_ROUT_14 (BIT29 | BIT28) +#define B_PCH_PMC_GPI_ROUT_15 (BIT31 | BIT30) + +#define R_PCH_PMC_PCC0 0x60 // Platform Clock Control 0 +#define B_PCH_PMC_PCC0_CLK_FREQ BIT2 // Clock Frequency +#define B_PCH_PMC_PCC0_CLK_CTL (BIT1 | BIT0) // Clock Gating + +#define R_PCH_PMC_PCC1 0x64 // Platform Clock Control 1 +#define B_PCH_PMC_PCC1_CLK_FREQ BIT2 // Clock Frequency +#define B_PCH_PMC_PCC1_CLK_CTL (BIT1 | BIT0) // Clock Gating + +#define R_PCH_PMC_PCC2 0x68 // Platform Clock Control 2 +#define B_PCH_PMC_PCC2_CLK_FREQ BIT2 // Clock Frequency +#define B_PCH_PMC_PCC2_CLK_CTL (BIT1 | BIT0) // Clock Gating + +#define R_PCH_PMC_PCC3 0x6C // Platform Clock Control 3 +#define B_PCH_PMC_PCC3_CLK_FREQ BIT2 // Clock Frequency +#define B_PCH_PMC_PCC3_CLK_CTL (BIT1 | BIT0) // Clock Gating + +#define R_PCH_PMC_PCC4 0x70 // Platform Clock Control 4 +#define B_PCH_PMC_PCC4_CLK_FREQ BIT2 // Clock Frequency +#define B_PCH_PMC_PCC4_CLK_CTL (BIT1 | BIT0) // Clock Gating + +#define R_PCH_PMC_PCC5 0x74 // Platform Clock Control 5 +#define B_PCH_PMC_PCC5_CLK_FREQ BIT2 // Clock Frequency +#define B_PCH_PMC_PCC5_CLK_CTL (BIT1 | BIT0) // Clock Gating + +#define R_PCH_PMC_S0IR_TMR 0x80 // S0I Ready Residency Timer +#define B_PCH_PMC_S0IR_TMR_RTIME 0xFFFFFFFF // Time Spent in S0I Ready State + +#define R_PCH_PMC_S0I1_TMR 0x84 // S0I1 Ready Residency Timer +#define B_PCH_PMC_S0I1_TMR_RTIME 0xFFFFFFFF // Time Spent in S0I1 Ready State + +#define R_PCH_PMC_S0I2_TMR 0x88 // S0I2 Ready Residency Timer +#define B_PCH_PMC_S0I2_TMR_RTIME 0xFFFFFFFF // Time Spent in S0I2 Ready State + +#define R_PCH_PMC_S0I3_TMR 0x8C // S0I3 Ready Residency Timer +#define B_PCH_PMC_S0I3_TMR_RTIME 0xFFFFFFFF // Time Spent in S0I3 Ready State + +#define R_PCH_PMC_S0_TMR 0x90 // S0 Residency Timer +#define B_PCH_PMC_S0_TMR_RTIME 0xFFFFFFFF // Time Spent in S0 State + +#define R_PCH_PMC_PSS 0x98 // Power Island Power Status +#define B_PCH_PMC_PSS_PG_STS 0x3FFFF // Power Gate Status of All Power Islands +#define B_PCH_PMC_PSS_PG_STS_USB_SUS BIT17 // USB SUS +#define B_PCH_PMC_PSS_PG_STS_USB BIT16 // USB +#define B_PCH_PMC_PSS_PG_STS_OTG_VCCACLK BIT15 // OTG VCCACLK +#define B_PCH_PMC_PSS_PG_STS_OTG VCCA BIT14 // OTG VCCA +#define B_PCH_PMC_PSS_PG_STS_OTG_VCCS BIT13 // OTG VCCS +#define B_PCH_PMC_PSS_PG_STS_OTG_CTL BIT12 // OTG Control +#define B_PCH_PMC_PSS_PG_STS_USH_VCCA BIT11 // USH VCCA +#define B_PCH_PMC_PSS_PG_STS_USH_VCCS BIT10 // USH VCCS +#define B_PCH_PMC_PSS_PG_STS_USH_SUS BIT9 // USH SUS +#define B_PCH_PMC_PSS_PG_STS_USH_CTL BIT8 // USH Control +#define B_PCH_PMC_PSS_PG_STS_DFX BIT7 // DFX +#define B_PCH_PMC_PSS_PG_STS_LPE BIT6 // LPE Audio +#define B_PCH_PMC_PSS_PG_STS_LPSS BIT5 // LPSS +#define B_PCH_PMC_PSS_PG_STS_PCIE BIT4 // PCIe +#define B_PCH_PMC_PSS_PG_STS_HDA BIT2 // HDA +#define B_PCH_PMC_PSS_PG_STS_SATA BIT1 // SATA + +#define R_PCH_PMC_D3_STS_0 0xA0 // D3 Status 0 +#define B_PCH_PMC_D3_STS_0_LPSS1F7 BIT31 // LPSS 1 Function 7 +#define B_PCH_PMC_D3_STS_0_LPSS1F6 BIT30 // LPSS 1 Function 6 +#define B_PCH_PMC_D3_STS_0_LPSS1F5 BIT29 // LPSS 1 Function 5 +#define B_PCH_PMC_D3_STS_0_LPSS1F4 BIT28 // LPSS 1 Function 4 +#define B_PCH_PMC_D3_STS_0_LPSS1F3 BIT27 // LPSS 1 Function 3 +#define B_PCH_PMC_D3_STS_0_LPSS1F2 BIT26 // LPSS 1 Function 2 +#define B_PCH_PMC_D3_STS_0_LPSS1F1 BIT25 // LPSS 1 Function 1 +#define B_PCH_PMC_D3_STS_0_LPSS1F0 BIT24 // LPSS 1 Function 0 +#define B_PCH_PMC_D3_STS_0_PCIEF3 BIT23 // PCIe Function 3 +#define B_PCH_PMC_D3_STS_0_PCIEF2 BIT22 // PCIe Function 2 +#define B_PCH_PMC_D3_STS_0_PCIEF1 BIT21 // PCIe Function 1 +#define B_PCH_PMC_D3_STS_0_PCIEF0 BIT20 // PCIe Function 0 +#define B_PCH_PMC_D3_STS_0_USB BIT18 // USB +#define B_PCH_PMC_D3_STS_0_SATA BIT17 // SATA +#define B_PCH_PMC_D3_STS_0_USH BIT15 // USH +#define B_PCH_PMC_D3_STS_0_OTG BIT14 // OTG +#define B_PCH_PMC_D3_STS_0_LPE BIT13 // LPE +#define B_PCH_PMC_D3_STS_0_HDA BIT12 // HDA +#define B_PCH_PMC_D3_STS_0_MIPI BIT11 // MIPI-HSI +#define B_PCH_PMC_D3_STS_0_SCCF2 BIT10 // SCC Function 2 +#define B_PCH_PMC_D3_STS_0_SCCF1 BIT9 // SCC Function 1 +#define B_PCH_PMC_D3_STS_0_SCCF0 BIT8 // SCC Function 0 +#define B_PCH_PMC_D3_STS_0_LPSS0F7 BIT7 // LPSS 0 Function 7 +#define B_PCH_PMC_D3_STS_0_LPSS0F6 BIT6 // LPSS 0 Function 6 +#define B_PCH_PMC_D3_STS_0_LPSS0F5 BIT5 // LPSS 0 Function 5 +#define B_PCH_PMC_D3_STS_0_LPSS0F4 BIT4 // LPSS 0 Function 4 +#define B_PCH_PMC_D3_STS_0_LPSS0F3 BIT3 // LPSS 0 Function 3 +#define B_PCH_PMC_D3_STS_0_LPSS0F2 BIT2 // LPSS 0 Function 2 +#define B_PCH_PMC_D3_STS_0_LPSS0F1 BIT1 // LPSS 0 Function 1 +#define B_PCH_PMC_D3_STS_0_LPSS0F0 BIT0 // LPSS 0 Function 0 + +#define R_PCH_PMC_D3_STS_1 0xA4 // D3 Status 1 +#define B_PCH_PMC_D3_STS_1_DFX BIT3 // DFX +#define B_PCH_PMC_D3_STS_1_OTG_SS BIT2 // OTG SS +#define B_PCH_PMC_D3_STS_1_USH_SS BIT1 // USH SS +#define B_PCH_PMC_D3_STS_1_SMB BIT0 // SMBus +#define R_PCH_PMC_D3_STDBY_STS_0 0xA8 // D3 Standby Status 0 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS1F7 BIT31 // LPSS 1 Function 7 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS1F6 BIT30 // LPSS 1 Function 6 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS1F5 BIT29 // LPSS 1 Function 5 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS1F4 BIT28 // LPSS 1 Function 4 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS1F3 BIT27 // LPSS 1 Function 3 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS1F2 BIT26 // LPSS 1 Function 2 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS1F1 BIT25 // LPSS 1 Function 1 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS1F0 BIT24 // LPSS 1 Function 0 +#define B_PCH_PMC_D3_STDBY_STS_0_PCIEF3 BIT23 // PCIe Function 3 +#define B_PCH_PMC_D3_STDBY_STS_0_PCIEF2 BIT22 // PCIe Function 2 +#define B_PCH_PMC_D3_STDBY_STS_0_PCIEF1 BIT21 // PCIe Function 1 +#define B_PCH_PMC_D3_STDBY_STS_0_PCIEF0 BIT20 // PCIe Function 0 +#define B_PCH_PMC_D3_STDBY_STS_0_USB BIT18 // USB +#define B_PCH_PMC_D3_STDBY_STS_0_SATA BIT17 // SATA +#define B_PCH_PMC_D3_STDBY_STS_0_USH BIT15 // USH +#define B_PCH_PMC_D3_STDBY_STS_0_OTG BIT14 // OTG +#define B_PCH_PMC_D3_STDBY_STS_0_LPE BIT13 // LPE +#define B_PCH_PMC_D3_STDBY_STS_0_HDA BIT12 // HDA +#define B_PCH_PMC_D3_STDBY_STS_0_MIPI BIT11 // MIPI-HSI +#define B_PCH_PMC_D3_STDBY_STS_0_SCCF2 BIT10 // SCC Function 2 +#define B_PCH_PMC_D3_STDBY_STS_0_SCCF1 BIT9 // SCC Function 1 +#define B_PCH_PMC_D3_STDBY_STS_0_SCCF0 BIT8 // SCC Function 0 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS0F7 BIT7 // LPSS 0 Function 7 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS0F6 BIT6 // LPSS 0 Function 6 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS0F5 BIT5 // LPSS 0 Function 5 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS0F4 BIT4 // LPSS 0 Function 4 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS0F3 BIT3 // LPSS 0 Function 3 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS0F2 BIT2 // LPSS 0 Function 2 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS0F1 BIT1 // LPSS 0 Function 1 +#define B_PCH_PMC_D3_STDBY_STS_0_LPSS0F0 BIT0 // LPSS 0 Function 0 + +#define R_PCH_PMC_D3_STDBY_STS_1 0xAC // D3 Standby Status 1 +#define B_PCH_PMC_D3_STDBY_STS_1_DFX BIT3 // DFX +#define B_PCH_PMC_D3_STDBY_STS_1_OTG_SS BIT2 // OTG SS +#define B_PCH_PMC_D3_STDBY_STS_1_USH_SS BIT1 // USH SS +#define B_PCH_PMC_D3_STDBY_STS_1_SMB BIT0 // SMBus + +#define R_PCH_PMC_MTPMC1 0xB0 // Message to PMC 1 + +#define R_PCH_PMC_MTPMC2 0xB4 // Message to PMC 2 + +#define R_PCH_PMC_MTPMC3 0xB8 // Message to PMC 3 + +#define R_PCH_PMC_MTPMC4 0xBC // Message to PMC 4 + +// +// IO Memory Space Registers (IOBASE) +// +#define R_PCH_CFIO_PAD_CONF0 0x00 // CFIO PAD_CONF0 +#define R_PCH_CFIO_PAD_CONF1 0x04 // CFIO PAD_CONF1 +#define R_PCH_CFIO_PAD_VAL 0x08 // CFIO PAD_VAL +#define R_PCH_CFIO_PAD_DFT 0x0C // CFIO PAD_CFT + +// +// GPIO Register Offsets from GBASE +// +#define R_PCH_GPIO_SC_USE_SEL 0x00 // GPIO South Usage Select [31:0] +#define R_PCH_GPIO_SC_IO_SEL 0x04 // GPIO South Input / Output Select [31:0] +#define R_PCH_GPIO_SC_LVL 0x08 // GPIO South Level for Input or Output [31:0] + +#define R_PCH_GPIO_SC_TPE 0x0C // GPIO South Trigger Positive Edge Enable [31:0] +#define R_PCH_GPIO_SC_TNE 0x10 // GPIO South Trigger Negative Edge Enable [31:0] +#define R_PCH_GPIO_SC_TS 0x14 // GPIO South Trigger Status [31:0] + +#define R_PCH_GPIO_SC_USE_SEL2 0x20 // GPIO South Usage Select 2 [63:32] +#define R_PCH_GPIO_SC_IO_SEL2 0x24 // GPIO South Input / Output Select 2 [63:32] +#define R_PCH_GPIO_SC_LVL2 0x28 // GPIO South Level for Input or Output 2 [63:32] + +#define R_PCH_GPIO_SC_TPE2 0x2C // GPIO South Trigger Positive Edge Enable 2 [63:32] +#define R_PCH_GPIO_SC_TNE2 0x30 // GPIO South Trigger Negative Edge Enable 2 [63:32] +#define R_PCH_GPIO_SC_TS2 0x34 // GPIO South Trigger Status 2 [63:32] + +#define R_PCH_GPIO_SC_USE_SEL3 0x40 // GPIO South Usage Select 3 [95:64] +#define R_PCH_GPIO_SC_IO_SEL3 0x44 // GPIO South Input / Output Select 3 [95:64] +#define R_PCH_GPIO_SC_LVL3 0x48 // GPIO South Level for Input or Output 3 [95:64] + +#define R_PCH_GPIO_SC_TPE3 0x4C // GPIO South Trigger Positive Edge Enable 3 [95:64] +#define R_PCH_GPIO_SC_TNE3 0x50 // GPIO South Trigger Negative Edge Enable 3 [95:64] +#define R_PCH_GPIO_SC_TS3 0x54 // GPIO South Trigger Status 3 [95:64] + +#define R_PCH_GPIO_SC_USE_SEL4 0x60 // GPIO South Usage Select 4 [127:96] +#define R_PCH_GPIO_SC_IO_SEL4 0x64 // GPIO South Input / Output Select 4 [127:96] +#define R_PCH_GPIO_SC_LVL4 0x68 // GPIO South Level for Input or Output 4 [127:96] + +#define R_PCH_GPIO_SC_TPE4 0x6C // GPIO South Trigger Positive Edge Enable 4 [127:96] +#define R_PCH_GPIO_SC_TNE4 0x70 // GPIO South Trigger Negative Edge Enable 4 [127:96] +#define R_PCH_GPIO_SC_TS4 0x74 // GPIO South Trigger Status 4 [127:96] + +#define R_PCH_GPIO_SUS_USE_SEL 0x80 // GPIO Suspend Use Select [31:0] +#define R_PCH_GPIO_SUS_IO_SEL 0x84 // GPIO Suspend Input / Output Select [31:0] +#define R_PCH_GPIO_SUS_LVL 0x88 // GPIO Suspend Level for Input or Output [31:0] + +#define R_PCH_GPIO_SUS_TPE 0x8C // GPIO Suspend Trigger Positive Edge Enable [31:0] +#define R_PCH_GPIO_SUS_TNE 0x90 // GPIO Suspend Trigger Negative Edge Enable [31:0] +#define R_PCH_GPIO_SUS_TS 0x94 // GPIO Suspend Trigger Status [31:0] + +#define R_PCH_GPIO_SUS_WAKE_EN 0x98 // GPIO Suspend Wake Enable [31:0] + +#define R_PCH_GPIO_SUS_USE_SEL2 0x100 // GPIO Suspend Use Select 2 [42:32] +#define R_PCH_GPIO_SUS_IO_SEL2 0x104 // GPIO Suspend Input / Output Select 2 [42:32] +#define R_PCH_GPIO_SUS_LVL2 0x108 // GPIO Suspend Level for Input or Output 2 [42:32] + +#define R_PCH_GPIO_SUS_TPE2 0x10C // GPIO Suspend Trigger Positive Edge Enable [42:32] +#define R_PCH_GPIO_SUS_TNE2 0x110 // GPIO Suspend Trigger Negative Edge Enable [42:32] +#define R_PCH_GPIO_SUS_TS2 0x114 // GPIO Suspend Trigger Status [42:32] + +#define R_PCH_GPIO_SUS_WAKE_EN2 0x118 // GPIO Suspend Wake Enable 2 [42:32] + +// +// Fixed IO Space +// + +// +// Processor Interface Registers +// +#define R_PCH_NMI_SC 0x61 // NMI Status and Control +#define B_PCH_NMI_SC_SERR_NMI_STS BIT7 // SERR# NMI Status +#define B_PCH_NMI_SC_IOCHK_NMI_STS BIT6 // IOCHK NMI Status +#define B_PCH_NMI_SC_TMR2_OUT_STS BIT5 // Timer Counter 2 Status +#define B_PCH_NMI_SC_REF_TOGGLE BIT4 // Refresh Cycle toggle Status +#define B_PCH_NMI_SC_IOCHK_NMI_EN BIT3 // IOCHK NMI Enable +#define B_PCH_NMI_SC_PCI_SERR_EN BIT2 // SERR# NMI Enable +#define B_PCH_NMI_SC_SPKR_DAT_EN BIT1 // Speaker Data Enable +#define B_PCH_NMI_SC_TIM_CNT2_EN BIT0 // Timer Counter 2 Enable + +#define R_PCH_NMI_EN 0x70 // NMI Enable and Real Time Clock Index, Co-function with R_PCH_RTC_INDEX +#define B_PCH_NMI_EN_NMI_EN BIT7 // NMI Enable, must preserve this bit first before writing to IO port 0x70 + +// +// RTC Registers +// +#define R_PCH_RTC_INDEX 0x70 // NMI Enable and Real Time Clock Index, Co-function with R_PCH_NMI_EN +#define R_PCH_RTC_TARGET 0x71 // Real-Time Clock Target Register +#define R_PCH_RTC_EXT_INDEX 0x72 // Extended RAM Index Register +#define R_PCH_RTC_EXT_TARGET 0x73 // Extended RAM Target Register +#define R_PCH_RTC_INDEX2 0x74 // Real-Time Clock Index Register +#define R_PCH_RTC_TARGET2 0x75 // Real-Time Clock Target Register +#define R_PCH_RTC_EXT_INDEX2 0x76 // Extended RAM Index Register +#define R_PCH_RTC_EXT_TARGET2 0x77 // Extended RAM Target Register + +#define R_PCH_RTC_SECONDS 0x00 // Seconds, Range 0..59 +#define R_PCH_RTC_SECONDSALARM 0x01 // Seconds Alarm, Range 0..59 +#define R_PCH_RTC_MINUTES 0x02 // Minutes, Range 0..59 +#define R_PCH_RTC_MINUTESALARM 0x03 // Minutes Alarm, Range 0..59 +#define R_PCH_RTC_HOURS 0x04 // Hours, Range 1..12 or 0..23 Bit 7 is AM/PM +#define R_PCH_RTC_HOURSALARM 0x05 // Hours Alarm, Range 1..12 or 0..23 Bit 7 is AM/PM +#define R_PCH_RTC_DAYOFWEEK 0x06 // Day of Week, Range 1..7 +#define R_PCH_RTC_DAYOFMONTH 0x07 // Day of Month, Range 1..31 +#define R_PCH_RTC_MONTH 0x08 // Month, Range 1..12 +#define R_PCH_RTC_YEAR 0x09 // Year, Range 0..99 + +#define R_PCH_RTC_REGISTERA 0x0A // RTC Register A +#define B_PCH_RTC_REGISTERA_UIP BIT7 // Update In Progress +#define B_PCH_RTC_REGISTERA_DV (BIT6 | BIT5 | BIT4) // Division Chain Select +#define V_PCH_RTC_REGISTERA_DV_NORM_OP 0x20 // Normal Operation +#define V_PCH_RTC_REGISTERA_DV_BYP_5 0x30 // Bypass 5 Stages (Test mode only) +#define V_PCH_RTC_REGISTERA_DV_BYP_10 0x40 // Bypass 10 Stages (Test mode only) +#define V_PCH_RTC_REGISTERA_DV_BYP_15 0x50 // Bypass 15 Stages (Test mode only) +#define V_PCH_RTC_REGISTERA_DV_DIV_RST1 0x60 // Divider Reset +#define V_PCH_RTC_REGISTERA_DV_DIV_RST2 0x70 // Divider Reset +#define B_PCH_RTC_REGISTERA_RS (BIT3 | BIT2 | BIT1 | BIT0) // Rate Select +#define V_PCH_RTC_REGISTERA_RS_INT_NV_TGL 0x00 // Interrupt Never Toggles +#define V_PCH_RTC_REGISTERA_RS_3P906MS1 0x01 // 3.90625 ms +#define V_PCH_RTC_REGISTERA_RS_7P812MS1 0x02 // 7.8125 ms +#define V_PCH_RTC_REGISTERA_RS_122P0US 0x03 // 122.070 us +#define V_PCH_RTC_REGISTERA_RS_244P1US 0x04 // 244.141 us +#define V_PCH_RTC_REGISTERA_RS_488P2US 0x05 // 488.281 us +#define V_PCH_RTC_REGISTERA_RS_976P5US 0x06 // 976.5625 us +#define V_PCH_RTC_REGISTERA_RS_1P953MS 0x07 // 1.953125 ms +#define V_PCH_RTC_REGISTERA_RS_3P906MS 0x08 // 3.90625 ms +#define V_PCH_RTC_REGISTERA_RS_7P812MS 0x09 // 7.8125 ms +#define V_PCH_RTC_REGISTERA_RS_15P62MS 0x0A // 15.625 ms +#define V_PCH_RTC_REGISTERA_RS_31P25MS 0x0B // 31.25 ms +#define V_PCH_RTC_REGISTERA_RS_62P5MS 0x0C // 62.5 ms +#define V_PCH_RTC_REGISTERA_RS_125MS 0x0D // 125 ms +#define V_PCH_RTC_REGISTERA_RS_250MS 0x0E // 250 ms +#define V_PCH_RTC_REGISTERA_RS_500MS 0x0F // 500 ms + +#define R_PCH_RTC_REGISTERB 0x0B // RTC Register B +#define B_PCH_RTC_REGISTERB_SET BIT7 // Update Cycle Inhibit 1: Stop auto update, begin set value; 0: Update cycle occurs +#define B_PCH_RTC_REGISTERB_PIE BIT6 // Periodic Interrupt Enable +#define B_PCH_RTC_REGISTERB_AIE BIT5 // Alarm Interrupt Enable +#define B_PCH_RTC_REGISTERB_UIE BIT4 // Update-ended Interrupt Enable +#define B_PCH_RTC_REGISTERB_SQWE BIT3 // Square Wave Enable (Not implemented) +#define B_PCH_RTC_REGISTERB_DM BIT2 // Data Mode 1: Binary; 0:BCD +#define B_PCH_RTC_REGISTERB_HF BIT1 // Hour Format 1: 24 mode; 0: 12 mode. +#define B_PCH_RTC_REGISTERB_DSE BIT0 // Daylight Savings Enable (Not Implemented) + +#define R_PCH_RTC_REGISTERC 0x0C // RTC Register C +#define B_PCH_RTC_REGISTERC_IRQF BIT7 // Interrupt Request Flag +#define B_PCH_RTC_REGISTERC_PF BIT6 // Periodic Interrupt Flag +#define B_PCH_RTC_REGISTERC_AF BIT5 // Alarm Flag +#define B_PCH_RTC_REGISTERC_UF BIT4 // Update-ended Flag +#define B_PCH_RTC_REGISTERC_RESERVED (BIT3 | BIT2 | BIT1 | BIT0) + +#define R_PCH_RTC_REGISTERD 0x0D // RTC Register D +#define B_PCH_RTC_REGISTERD_VRT BIT7 // Valid RAM and Time Bit +#define B_PCH_RTC_REGISTERD_RESERVED BIT6 +#define B_PCH_RTC_REGISTERD_DA 0x3F // Date Alarm + +#define B_PCH_RTC_CENTURY 0x32 // Century Data + +// +// APM Registers +// +#define R_PCH_APM_CNT 0xB2 // Advanced Power Management Control Port +#define R_PCH_APM_STS 0xB3 // Advanced Power Management Status Port + +// +// INIT Register +// +#define R_PCH_PORT92 0x92 +#define B_PCH_PORT92_ALT_A20_GATE BIT1 // Alternate A20 Gate +#define B_PCH_PORT92_INIT_NOW BIT0 // Init Now + +// +// PCU UART +// +#define R_PCH_COM1_BASE 0x3F8 // COM1 IO BASE + +// +// Reset Control Register +// +#define R_PCH_RST_CNT 0xCF9 // Reset Control +#define B_PCH_RST_CNT_FULL_RST BIT3 +#define B_PCH_RST_CNT_RST_CPU BIT2 +#define B_PCH_RST_CNT_SYS_RST BIT1 +#define V_PCH_RST_CNT_FULLRESET 0x0E +#define V_PCH_RST_CNT_HARDRESET 0x06 +#define V_PCH_RST_CNT_SOFTRESET 0x04 // Not supported by VLV +#define V_PCH_RST_CNT_HARDSTARTSTATE 0x02 +#define V_PCH_RST_CNT_SOFTSTARTSTATE 0x00 + +// +// Fixed Memory Region +// + +// +// IO APIC Registers +// +#define R_PCH_IO_APIC_INDEX 0xFEC00000 // IOAPIC Index Register, 8bit +#define R_PCH_IO_APIC_WINDOW 0xFEC00010 // IOAPIC Window Register, 32bit +#define R_PCH_IO_APIC_EOI 0xFEC00040 // IOAPIC EOI Register, 8bit + +#define R_PCH_IO_APIC_ID 0x00 // Identification +#define B_PCH_IO_APIC_ID_AID (BIT27 | BIT26 | BIT25 | BIT24) // APIC Identification + +#define R_PCH_IO_APIC_VS 0x01 // Version +#define B_PCH_IO_APIC_VS_MRE 0xFF0000 // Maximum Redirection Entries +#define B_PCH_IO_APIC_VS_PRQ BIT15 // Pin Assertion Register Supported +#define B_PCH_IO_APIC_VS_VS 0xFF // Version + +// +// HPET Registers +// +#define R_PCH_PCH_HPET 0xFED00000 // HPET Base Address + +#define R_PCH_PCH_HPET_GCID 0x00 // HPET General Capabilities and ID, 64bit +#define B_PCH_PCH_HPET_GCID_CTP 0xFFFFFFFF00000000 // Counter Tick Period +#define B_PCH_PCH_HPET_GCID_VID 0xFFFF0000 // Vendor ID +#define B_PCH_PCH_HPET_GCID_LRC BIT15 // Legacy Rout Capable +#define B_PCH_PCH_HPET_GCID_CS BIT13 // Counter Size +#define B_PCH_PCH_HPET_GCID_NT 0x1F00 // Number of Timers +#define B_PCH_PCH_HPET_GCID_RID 0xFF // Revision ID +#define N_PCH_HPET_ADDR_ASEL 12 + +#define R_PCH_PCH_HPET_GCFG 0x10 // HPET General Configuration +#define B_PCH_PCH_HPET_GCFG_LRE BIT1 // Legacy Rout Enable +#define B_PCH_PCH_HPET_GCFG_EN BIT0 // Overall Enable + +#define R_PCH_PCH_HPET_GIS 0x20 // HPET General Interrupt Status +#define B_PCH_PCH_HPET_GIS_T2 BIT2 // Timer 2 Status +#define B_PCH_PCH_HPET_GIS_T1 BIT1 // Timer 1 Status +#define B_PCH_PCH_HPET_GIS_T0 BIT0 // Timer 0 Status + +#define R_PCH_PCH_HPET_MCV 0xF0 // HPET Main Counter Value, 64bit + +#define R_PCH_PCH_HPET_T0C 0x100 // HPET Timer 0 Config and Capabilities +#define R_PCH_PCH_HPET_T0CV_L 0x108 // HPET Timer 0 Lower Comparator Value +#define R_PCH_PCH_HPET_T0CV_H 0x10C // HPET Timer 0 Upper Comparator Value + +#define R_PCH_PCH_HPET_T1C 0x120 // HPET Timer 1 Config and Capabilities +#define R_PCH_PCH_HPET_T1CV 0x128 // HPET Timer 1 Comparator Value + +#define R_PCH_PCH_HPET_T2C 0x140 // HPET Timer 2 Config and Capabilities +#define R_PCH_PCH_HPET_T2CV 0x148 // HPET Timer 2 Comparator Value + +#define B_PCH_PCH_HPET_TXC_IRC 0xFFFFFFFF00000000 // Interrupt Rout Capability +#define B_PCH_PCH_HPET_TXC_FID BIT15 // FSB Interrupt Delivery +#define B_PCH_PCH_HPET_TXC_FE BIT14 // FSB Enable +#define B_PCH_PCH_HPET_TXC_IR 0x3E00 // Interrupt Rout +#define B_PCH_PCH_HPET_TXC_T32M BIT8 // Timer 32-bit Mode +#define B_PCH_PCH_HPET_TXC_TVS BIT6 // Timer Value Set +#define B_PCH_PCH_HPET_TXC_TS BIT5 // Timer Size +#define B_PCH_PCH_HPET_TXC_PIC BIT4 // Periodic Interrupt Capable +#define B_PCH_PCH_HPET_TXC_TYP BIT3 // Timer Type +#define B_PCH_PCH_HPET_TXC_IE BIT2 // Interrupt Enable +#define B_PCH_PCH_HPET_TXC_IT BIT1 // Timer Interrupt Type + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsRcrb.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsRcrb.h new file mode 100644 index 0000000000..32f36458ad --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsRcrb.h @@ -0,0 +1,54 @@ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchRegsRcrb.h + + @brief + Register names for VLV Chipset Configuration Registers + + Conventions: + + - Prefixes: + 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 + - In general, PCH registers are denoted by "_PCH_" in register names + - Registers / bits that are different between PCH generations are denoted by + "_PCH__" in register/bit names. e.g., "_PCH_VLV_" + - Registers / bits that are different between SKUs are denoted by "_" + at the end of the register/bit names + - Registers / bits of new devices introduced in a PCH generation will be just named + as "_PCH_" without inserted. + +**/ +#ifndef _PCH_REGS_RCRB_H_ +#define _PCH_REGS_RCRB_H_ + +/// +/// Chipset Configuration Registers (Memory space) +/// RCBA +/// +#define R_PCH_RCRB_GCS 0x00 // General Control and Status +#define B_PCH_RCRB_GCS_BBSIZE (BIT30 | BIT29) // Boot Block Size +#define B_PCH_RCRB_GCS_BBS (BIT11 | BIT10) // Boot BIOS Straps +#define V_PCH_RCRB_GCS_BBS_SPI (3 << 10) // Boot BIOS strapped to SPI +#define V_PCH_RCRB_GCS_BBS_LPC (0 << 10) // Boot BIOS strapped to LPC +#define B_PCH_RCRB_GCS_TS BIT1 // Top Swap +#define B_PCH_RCRB_GCS_BILD BIT0 // BIOS Interface Lock-Down + + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsSata.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsSata.h new file mode 100644 index 0000000000..7b86de3831 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsSata.h @@ -0,0 +1,251 @@ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchRegsSata.h + + @brief + Register names for VLV SATA controllers + + Conventions: + + - Prefixes: + 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 + - In general, PCH registers are denoted by "_PCH_" in register names + - Registers / bits that are different between PCH generations are denoted by + "_PCH__" in register/bit names. e.g., "_PCH_VLV_" + - Registers / bits that are different between SKUs are denoted by "_" + at the end of the register/bit names + - Registers / bits of new devices introduced in a PCH generation will be just named + as "_PCH_" without inserted. + +**/ +#ifndef _PCH_REGS_SATA_H_ +#define _PCH_REGS_SATA_H_ + +/// +/// VLV SATA Message Bus +/// +#define PCH_SATA_PHY_PORT_ID 0xA3 // SATA PHY Port ID +#define PCH_SATA_PHY_MMIO_READ_OPCODE 0x00 // CUnit to SATA PHY MMIO Read Opcode +#define PCH_SATA_PHY_MMIO_WRITE_OPCODE 0x01 // CUnit to SATA PHY MMIO Write Opcode + +/// +/// SATA Controller Registers (D19:F0) +/// +#define PCI_DEVICE_NUMBER_PCH_SATA 19 +#define PCI_FUNCTION_NUMBER_PCH_SATA 0 + +#define R_PCH_SATA_ID 0x00 // Identifiers +#define B_PCH_SATA_ID_DID 0xFFFF0000 // Device ID +#define B_PCH_SATA_ID_VID 0x0000FFFF // Vendor ID +#define V_PCH_SATA_VENDOR_ID V_PCH_INTEL_VENDOR_ID +#define V_PCH_SATA_DEVICE_ID_D_IDE 0x0F20 // Desktop IDE Mode (Ports 0 and 1) +#define V_PCH_SATA_DEVICE_ID_D_AHCI 0x0F22 // Desktop AHCI Mode (Ports 0 and 1) +#define V_PCH_SATA_DEVICE_ID_D_RAID 0x2822 // Desktop RAID 0/1/5/10 Mode, based on D19:F0:9Ch[7] + +#define V_PCH_SATA_DEVICE_ID_M_IDE 0x0F21 // Mobile IDE Mode (Ports 0 and 1) +#define V_PCH_SATA_DEVICE_ID_M_AHCI 0x0F23 // Mobile AHCI Mode (Ports 0 and 1) +#define V_PCH_SATA_DEVICE_ID_M_RAID 0x282A // Mobile RAID 0/1/5/10 Mode, based on D19:F0:9Ch[7] + +#define R_PCH_SATA_COMMAND 0x04 // Command +#define B_PCH_SATA_COMMAND_INT_DIS BIT10 // Interrupt Disable +#define B_PCH_SATA_COMMAND_FBE BIT9 // Fast Back-to-back Enable +#define B_PCH_SATA_COMMAND_SERR_EN BIT8 // SERR# Enable +#define B_PCH_SATA_COMMAND_WCC BIT7 // Wait Cycle Enable +#define B_PCH_SATA_COMMAND_PER BIT6 // Parity Error Response Enable +#define B_PCH_SATA_COMMAND_VPS BIT5 // VGA Palette Snooping Enable +#define B_PCH_SATA_COMMAND_PMWE BIT4 // Memory Write and Invalidate Enable +#define B_PCH_SATA_COMMAND_SCE BIT3 // Special Cycle Enable +#define B_PCH_SATA_COMMAND_BME BIT2 // Bus Master Enable +#define B_PCH_SATA_COMMAND_MSE BIT1 // Memory Space Enable +#define B_PCH_SATA_COMMAND_IOSE BIT0 // I/O Space Enable + +#define R_PCH_SATA_PCISTS 0x06 // Device Status +#define B_PCH_SATA_PCISTS_DPE BIT15 // Detected Parity Error +#define B_PCH_SATA_PCISTS_SSE BIT14 // Signaled System Error +#define B_PCH_SATA_PCISTS_RMA BIT13 // Received Master-Abort Status +#define B_PCH_SATA_PCISTS_RTA BIT12 // Received Target-Abort Status +#define B_PCH_SATA_PCISTS_STA BIT11 // Signaled Target-Abort Status +#define B_PCH_SATA_PCISTS_DEV_STS_MASK (BIT10 | BIT9) // DEVSEL# Timing Status +#define B_PCH_SATA_PCISTS_DPED BIT8 // Master Data Parity Error Detected +#define B_PCH_SATA_PCISTS_CAP_LIST BIT4 // Capabilities List +#define B_PCH_SATA_PCISTS_ITNS BIT3 // Interrupt Status + +#define R_PCH_SATA_RID 0x08 // Revision ID (8 bits) + +#define R_PCH_SATA_PI_REGISTER 0x09 // Programming Interface (8 bits) +#define B_PCH_SATA_PI_REGISTER_SNC BIT3 // Secondary Mode Native Capable +#define B_PCH_SATA_PI_REGISTER_SNE BIT2 // Secondary Mode Native Enable +#define B_PCH_SATA_PI_REGISTER_PNC BIT1 // Primary Mode Native Capable +#define B_PCH_SATA_PI_REGISTER_PNE BIT0 // Primary Mode Native Enable + +#define R_PCH_SATA_CC 0x0A // Class Code +#define B_PCH_SATA_CC_BCC 0xFF00 // Base Class Code +#define B_PCH_SATA_CC_SCC 0x00FF // Sub Class Code +#define V_PCH_SATA_CC_SCC_IDE 0x01 +#define V_PCH_SATA_CC_SCC_AHCI 0x06 +#define V_PCH_SATA_CC_SCC_RAID 0x04 + +#define R_PCH_SATA_CLS 0x0C // Cache Line Size (8 bits) +#define B_PCH_SATA_CLS 0xFF + +#define R_PCH_SATA_MLT 0x0D // Master Latency Timer (8 bits) +#define B_PCH_SATA_MLT 0xFF + +#define R_PCH_SATA_HTYPE 0x0E // Header Type +#define B_PCH_SATA_HTYPE_MFD BIT7 // Multi-function Device +#define B_PCH_SATA_HTYPE_HL 0x7F // Header Layout + +#define R_PCH_SATA_PCMD_BAR 0x10 // Primary Command Block Base Address +#define B_PCH_SATA_PCMD_BAR_BA 0x0000FFF8 // Base Address +#define B_PCH_SATA_PCMD_BAR_RTE BIT0 // Resource Type Indicator + +#define R_PCH_SATA_PCTL_BAR 0x14 // Primary Control Block Base Address +#define B_PCH_SATA_PCTL_BAR_BA 0x0000FFFC // Base Address +#define B_PCH_SATA_PCTL_BAR_RTE BIT0 // Resource Type Indicator + +#define R_PCH_SATA_SCMD_BAR 0x18 // Secondary Command Block Base Address +#define B_PCH_SATA_SCMD_BAR_BA 0x0000FFF8 // Base Address +#define B_PCH_SATA_SCMD_BAR_RTE BIT0 // Resource Type Indicator + +#define R_PCH_SATA_SCTL_BAR 0x1C // Secondary Control Block Base Address +#define B_PCH_SATA_SCTL_BAR_BA 0x0000FFFC // Base Address +#define B_PCH_SATA_SCTL_BAR_RTE BIT0 // Resource Type Indicator + +#define R_PCH_SATA_LBAR 0x20 // Legacy IDE Base Address / AHCI Index Data Pair Base Address +#define B_PCH_SATA_LBAR_BA 0x0000FFE0 // Base Address +#define B_PCH_SATA_LBAR_BA4 BIT4 // Base Address 4 +#define B_PCH_SATA_LBAR_RTE BIT0 // Resource Type Indicator + +#define R_PCH_SATA_SIDPBA 0x24 // Serial ATA Index Data Pair Base Address +#define R_PCH_SATA_ABAR 0x24 // AHCI Base Address +#define B_PCH_SATA_ABAR_BA 0xFFFFF800 // AHCI Memory Base Address (When CC.SCC not equal 0x01) +#define V_PCH_SATA_ABAR_LENGTH 0x800 // AHCI Memory Length (When CC.SCC not equal 0x01) +#define N_PCH_SATA_ABAR_ALIGNMENT 11 // AHCI Base Address Alignment (When CC.SCC not equal 0x01) +#define B_PCH_SATA_SIDPBA_BA 0x0000FFF0 // Serial ATA Index Data Pair IO Base Address (When CC.SCC equal 0x01) +#define V_PCH_SATA_SIDPBA_LENGTH 0x10 // Serial ATA Index Data Pair IO Length (When CC.SCC equal 0x01) +#define N_PCH_SATA_SIDPBA_ALIGNMENT 4 // Serial ATA Index Data Pair Base Address Alignment (When CC.SCC not equal 0x01) +#define B_PCH_SATA_ABAR_PF BIT3 // Prefetchable +#define B_PCH_SATA_ABAR_TP (BIT2 | BIT1) // Type +#define B_PCH_SATA_ABAR_RTE BIT0 // Resource Type Indicator + +#define R_PCH_SATA_SS 0x2C // Sub System Identifiers +#define B_PCH_SATA_SS_SSID 0xFFFF0000 // Subsystem ID +#define B_PCH_SATA_SS_SSVID 0x0000FFFF // Subsystem Vendor ID + +#define R_PCH_SATA_AHCI_CAP_PTR 0x34 // Capabilities Pointer (8 bits) +#define B_PCH_SATA_AHCI_CAP_PTR 0xFF + +#define R_PCH_SATA_INTR 0x3C // Interrupt Information +#define B_PCH_SATA_INTR_IPIN 0xFFFF0000 // Interrupt Pin +#define B_PCH_SATA_INTR_ILINE 0x0000FFFF // Interrupt Line + +#define R_PCH_SATA_PMCS 0x74 // PCI Power Management Control and Status +#define B_PCH_SATA_PMCS_PMES BIT15 // PME Status +#define B_PCH_SATA_PMCS_PMEE BIT8 // PME Enable +#define B_PCH_SATA_PMCS_NSFRST BIT3 // No Soft Reset +#define V_PCH_SATA_PMCS_NSFRST_1 0x01 +#define V_PCH_SATA_PMCS_NSFRST_0 0x00 +#define B_PCH_SATA_PMCS_PS (BIT1 | BIT0) // Power State +#define V_PCH_SATA_PMCS_PS_3 0x03 +#define V_PCH_SATA_PMCS_PS_0 0x00 + +#define R_PCH_SATA_MAP 0x90 // Port Mapping Register +#define B_PCH_SATA_MAP_SPD (BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8) // SATA Port Disable +#define B_PCH_SATA_PORT6_DISABLED BIT14 +#define B_PCH_SATA_PORT5_DISABLED BIT13 +#define B_PCH_SATA_PORT4_DISABLED BIT12 +#define B_PCH_SATA_PORT3_DISABLED BIT11 +#define B_PCH_SATA_PORT2_DISABLED BIT10 +#define B_PCH_SATA_PORT1_DISABLED BIT9 +#define B_PCH_SATA_PORT0_DISABLED BIT8 +#define B_PCH_SATA_MAP_SMS_MASK (BIT7 | BIT6) // SATA Mode Select +#define V_PCH_SATA_MAP_SMS_IDE 0x00 +#define V_PCH_SATA_MAP_SMS_AHCI 0x40 +#define V_PCH_SATA_MAP_SMS_RAID 0x80 +#define B_PCH_SATA_PORT_TO_CONTROLLER_CFG BIT5 // SATA Port-to-Controller Configuration + +#define R_PCH_SATA_PCS 0x92 // Port Control and Status +#define S_PCH_SATA_PCS 0x2 +#define B_PCH_SATA_PCS_OOB_RETRY BIT15 // OOB Retry Mode +#define B_PCH_SATA_PCS_PORT6_DET BIT14 // Port 6 Present +#define B_PCH_SATA_PCS_PORT5_DET BIT13 // Port 5 Present +#define B_PCH_SATA_PCS_PORT4_DET BIT12 // Port 4 Present +#define B_PCH_SATA_PCS_PORT3_DET BIT11 // Port 3 Present +#define B_PCH_SATA_PCS_PORT2_DET BIT10 // Port 2 Present +#define B_PCH_SATA_PCS_PORT1_DET BIT9 // Port 1 Present +#define B_PCH_SATA_PCS_PORT0_DET BIT8 // Port 0 Present +#define B_PCH_SATA_PCS_PORT5_EN BIT5 // Port 5 Enabled +#define B_PCH_SATA_PCS_PORT4_EN BIT4 // Port 4 Enabled +#define B_PCH_SATA_PCS_PORT3_EN BIT3 // Port 3 Enabled +#define B_PCH_SATA_PCS_PORT2_EN BIT2 // Port 2 Enabled +#define B_PCH_SATA_PCS_PORT1_EN BIT1 // Port 1 Enabled +#define B_PCH_SATA_PCS_PORT0_EN BIT0 // Port 0 Enabled + +#define R_PCH_SATA_AHCI_PI 0x0C // Ports Implemented +#define B_PCH_SATA_PORT_MASK 0x3F +#define B_PCH_SATA_PORT5_IMPLEMENTED BIT5 // Port 5 Implemented +#define B_PCH_SATA_PORT4_IMPLEMENTED BIT4 // Port 4 Implemented +#define B_PCH_SATA_PORT3_IMPLEMENTED BIT3 // Port 3 Implemented +#define B_PCH_SATA_PORT2_IMPLEMENTED BIT2 // Port 2 Implemented +#define B_PCH_SATA_PORT1_IMPLEMENTED BIT1 // Port 1 Implemented +#define B_PCH_SATA_PORT0_IMPLEMENTED BIT0 // Port 0 Implemented + +#define R_PCH_SATA_AHCI_P0SSTS 0x128 // Port 0 Serial ATA Status +#define R_PCH_SATA_AHCI_P1SSTS 0x1A8 // Port 1 Serial ATA Status +#define B_PCH_SATA_AHCI_PXSSTS_IPM 0x00000F00 // Interface Power Management +#define B_PCH_SATA_AHCI_PXSSTS_IPM_0 0x00000000 +#define B_PCH_SATA_AHCI_PXSSTS_IPM_1 0x00000100 +#define B_PCH_SATA_AHCI_PXSSTS_IPM_2 0x00000200 +#define B_PCH_SATA_AHCI_PXSSTS_IPM_6 0x00000600 +#define B_PCH_SATA_AHCI_PXSSTS_SPD 0x000000F0 // Current Interface Speed +#define B_PCH_SATA_AHCI_PXSSTS_SPD_0 0x00000000 +#define B_PCH_SATA_AHCI_PXSSTS_SPD_1 0x00000010 +#define B_PCH_SATA_AHCI_PXSSTS_SPD_2 0x00000020 +#define B_PCH_SATA_AHCI_PXSSTS_SPD_3 0x00000030 +#define B_PCH_SATA_AHCI_PXSSTS_DET 0x0000000F // Device Detection +#define B_PCH_SATA_AHCI_PXSSTS_DET_0 0x00000000 +#define B_PCH_SATA_AHCI_PXSSTS_DET_1 0x00000001 +#define B_PCH_SATA_AHCI_PXSSTS_DET_3 0x00000003 +#define B_PCH_SATA_AHCI_PXSSTS_DET_4 0x00000004 + +// +// Macros of VLV capabilities for SATA controller which are used by SATA controller driver +// +// +// +// Define the individual capabilities of each SATA controller +// +#define PCH_SATA_MAX_CONTROLLERS 1 // Max SATA controllers number supported +#define PCH_SATA_MAX_DEVICES 2 // Max SATA devices number of single SATA channel +#define PCH_IDE_MAX_CHANNELS 2 // Max IDE channels number of single SATA controller +#define PCH_IDE_MAX_DEVICES 2 // Max IDE devices number of single SATA channel +#define PCH_AHCI_MAX_PORTS 2 // Max number of SATA ports in VLV +#define PCH_IDE_MAX_PORTS 2 // Max number of IDE ports in VLV + +// +// GPIOS_14 SATA0GP is the SATA port 0 reset pin. +// +#define PCH_GPIO_SATA_PORT0_RESET 14 +// +// GPIOS_15 SATA1GP is the SATA port 1 reset pin. +// +#define PCH_GPIO_SATA_PORT1_RESET 15 + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsScc.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsScc.h new file mode 100644 index 0000000000..7b1af9ce6b --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsScc.h @@ -0,0 +1,59 @@ +/*++ + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PchRegsScc.h + +Abstract: + + Register names for VLV SCC module. + + Conventions: + + - Prefixes: + 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 + - In general, PCH registers are denoted by "_PCH_" in register names + - Registers / bits that are different between PCH generations are denoted by + "_PCH__" in register/bit names. e.g., "_PCH_VLV_" + - Registers / bits that are different between SKUs are denoted by "_" + at the end of the register/bit names + - Registers / bits of new devices introduced in a PCH generation will be just named + as "_PCH_" without inserted. + +--*/ +#ifndef _PCH_REGS_SCC_H_ +#define _PCH_REGS_SCC_H_ + + +// +// SCC Modules Registers +// + +// +// SCC SDIO Modules +// PCI Config Space Registers +// +#define PCI_DEVICE_NUMBER_PCH_SCC_SDIO_0 16 +#define PCI_DEVICE_NUMBER_PCH_SCC_SDIO_1 17 +#define PCI_DEVICE_NUMBER_PCH_SCC_SDIO_2 18 +#define PCI_DEVICE_NUMBER_PCH_SCC_SDIO_3 23 + +#define PCI_FUNCTION_NUMBER_PCH_SCC_SDIO 0 + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsSmbus.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsSmbus.h new file mode 100644 index 0000000000..075974a128 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsSmbus.h @@ -0,0 +1,155 @@ +/** + +Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchRegsSmbus.h + + @brief + Register names for VLV Smbus Device. + + Conventions: + + - Prefixes: + 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 + - In general, PCH registers are denoted by "_PCH_" in register names + - Registers / bits that are different between PCH generations are denoted by + "_PCH__" in register/bit names. e.g., "_PCH_VLV_" + - Registers / bits that are different between SKUs are denoted by "_" + at the end of the register/bit names + - Registers / bits of new devices introduced in a PCH generation will be just named + as "_PCH_" without inserted. + +**/ +#ifndef _PCH_REGS_SMBUS_H_ +#define _PCH_REGS_SMBUS_H_ + +/// +/// SMBus Controller Registers (D31:F3) +/// +#define PCI_DEVICE_NUMBER_PCH_SMBUS 31 +#define PCI_FUNCTION_NUMBER_PCH_SMBUS 3 + +#define R_PCH_SMBUS_VENDOR_ID 0x00 // Vendor ID +#define V_PCH_SMBUS_VENDOR_ID V_PCH_INTEL_VENDOR_ID // Intel Vendor ID + +#define R_PCH_SMBUS_DEVICE_ID 0x02 // Device ID +#define V_PCH_SMBUS_DEVICE_ID 0x0F12 + +#define R_PCH_SMBUS_PCICMD 0x04 // CMD register enables/disables, Memory/IO space access and interrupt +#define B_PCH_SMBUS_PCICMD_INTR_DIS BIT10 // Interrupt Disable +#define B_PCH_SMBUS_PCICMD_FBE BIT9 // FBE - reserved as '0' +#define B_PCH_SMBUS_PCICMD_SERR_EN BIT8 // SERR Enable - reserved as '0' +#define B_PCH_SMBUS_PCICMD_WCC BIT7 // Wait Cycle Control - reserved as '0' +#define B_PCH_SMBUS_PCICMD_PER BIT6 // Parity Error - reserved as '0' +#define B_PCH_SMBUS_PCICMD_VPS BIT5 // VGA Palette Snoop - reserved as '0' +#define B_PCH_SMBUS_PCICMD_PMWE BIT4 // Postable Memory Write Enable - reserved as '0' +#define B_PCH_SMBUS_PCICMD_SCE BIT3 // Special Cycle Enable - reserved as '0' +#define B_PCH_SMBUS_PCICMD_BME BIT2 // Bus Master Enable - reserved as '0' +#define B_PCH_SMBUS_PCICMD_MSE BIT1 // Memory Space Enable +#define B_PCH_SMBUS_PCICMD_IOSE BIT0 // I/O Space Enable + +#define R_PCH_SMBUS_BASE 0x20 // The I/O memory bar +#define B_PCH_SMBUS_BASE_BAR 0x0000FFE0 // Base Address +#define B_PCH_SMBUS_BASE_IOSI BIT0 // IO Space Indicator + +#define R_PCH_SMBUS_SVID 0x2C // Subsystem Vendor ID +#define B_PCH_SMBUS_SVID 0xFFFF // Subsystem Vendor ID + +// +// SMBus I/O Registers +// +#define R_PCH_SMBUS_HSTS 0x00 // Host Status Register R/W +#define B_PCH_SMBUS_HSTS_ALL 0xFF +#define B_PCH_SMBUS_BYTE_DONE_STS BIT7 // Byte Done Status +#define B_PCH_SMBUS_IUS BIT6 // In Use Status +#define B_PCH_SMBUS_SMBALERT_STS BIT5 // SMBUS Alert +#define B_PCH_SMBUS_FAIL BIT4 // Failed +#define B_PCH_SMBUS_BERR BIT3 // Bus Error +#define B_PCH_SMBUS_DERR BIT2 // Device Error +#define B_PCH_SMBUS_ERRORS (B_PCH_SMBUS_FAIL | B_PCH_SMBUS_BERR | B_PCH_SMBUS_DERR) +#define B_PCH_SMBUS_INTR BIT1 // Interrupt +#define B_PCH_SMBUS_HBSY BIT0 // Host Busy + +#define R_PCH_SMBUS_HCTL 0x02 // Host Control Register R/W +#define B_PCH_SMBUS_PEC_EN BIT7 // Packet Error Checking Enable +#define B_PCH_SMBUS_START BIT6 // Start +#define B_PCH_SMBUS_LAST_BYTE BIT5 // Last Byte +#define B_PCH_SMBUS_SMB_CMD 0x1C // SMB Command +#define V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS 0x1C // Block Process +#define V_PCH_SMBUS_SMB_CMD_IIC_READ 0x18 // I2C Read +#define V_PCH_SMBUS_SMB_CMD_BLOCK 0x14 // Block +#define V_PCH_SMBUS_SMB_CMD_PROCESS_CALL 0x10 // Process Call +#define V_PCH_SMBUS_SMB_CMD_WORD_DATA 0x0C // Word Data +#define V_PCH_SMBUS_SMB_CMD_BYTE_DATA 0x08 // Byte Data +#define V_PCH_SMBUS_SMB_CMD_BYTE 0x04 // Byte +#define V_PCH_SMBUS_SMB_CMD_QUICK 0x00 // Quick +#define B_PCH_SMBUS_KILL BIT1 // Kill +#define B_PCH_SMBUS_INTREN BIT0 // Interrupt Enable + +#define R_PCH_SMBUS_HCMD 0x03 // Host Command Register R/W +#define B_PCH_SMBUS_HCMD 0xFF // Command to be transmitted + +#define R_PCH_SMBUS_TSA 0x04 // Transmit Slave Address Register R/W +#define B_PCH_SMBUS_ADDRESS 0xFE // 7-bit address of the targeted slave +#define B_PCH_SMBUS_RW_SEL BIT0 // Direction of the host transfer, 1 = read, 0 = write +#define B_PCH_SMBUS_RW_SEL_READ 0x01 // Read +#define B_PCH_SMBUS_RW_SEL_WRITE 0x00 // Write +// +#define R_PCH_SMBUS_HD0 0x05 // Data 0 Register R/W +#define R_PCH_SMBUS_HD1 0x06 // Data 1 Register R/W +#define R_PCH_SMBUS_HBD 0x07 // Host Block Data Register R/W +#define R_PCH_SMBUS_PEC 0x08 // Packet Error Check Data Register R/W + +#define R_PCH_SMBUS_RSA 0x09 // Receive Slave Address Register R/W +#define B_PCH_SMBUS_SLAVE_ADDR 0x7F // TCO slave address (Not used, reserved) + +#define R_PCH_SMBUS_SD 0x0A // Receive Slave Data Register R/W + +#define R_PCH_SMBUS_AUXS 0x0C // Auxiliary Status Register R/WC +#define B_PCH_SMBUS_CRCE BIT0 // CRC Error +// +#define R_PCH_SMBUS_AUXC 0x0D // Auxiliary Control Register R/W +#define B_PCH_SMBUS_E32B BIT1 // Enable 32-byte Buffer +#define B_PCH_SMBUS_AAC BIT0 // Automatically Append CRC + +#define R_PCH_SMBUS_SMLC 0x0E // SMLINK Pin Control Register R/W +#define B_PCH_SMBUS_SMLINK_CLK_CTL BIT2 // Not supported +#define B_PCH_SMBUS_SMLINK1_CUR_STS BIT1 // Not supported +#define B_PCH_SMBUS_SMLINK0_CUR_STS BIT0 // Not supported + + +#define R_PCH_SMBUS_SMBC 0x0F // SMBus Pin Control Register R/W +#define B_PCH_SMBUS_SMBCLK_CTL BIT2 // SMBCLK Control +#define B_PCH_SMBUS_SMBDATA_CUR_STS BIT1 // SMBDATA Current Status +#define B_PCH_SMBUS_SMBCLK_CUR_STS BIT0 // SMBCLK Current Status + +#define R_PCH_SMBUS_SSTS 0x10 // Slave Status Register R/WC +#define B_PCH_SMBUS_HOST_NOTIFY_STS BIT0 // Host Notify Status + +#define R_PCH_SMBUS_SCMD 0x11 // Slave Command Register R/W +#define B_PCH_SMBUS_SMBALERT_DIS BIT2 // Not supported +#define B_PCH_SMBUS_HOST_NOTIFY_WKEN BIT1 // Host Notify Wake Enable +#define B_PCH_SMBUS_HOST_NOTIFY_INTREN BIT0 // Host Notify Interrupt Enable + +#define R_PCH_SMBUS_NDA 0x14 // Notify Device Address Register RO +#define B_PCH_SMBUS_DEVICE_ADDRESS 0xFE // Device Address + +#define R_PCH_SMBUS_NDLB 0x16 // Notify Data Low Byte Register RO +#define R_PCH_SMBUS_NDHB 0x17 // Notify Data High Byte Register RO + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsSpi.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsSpi.h new file mode 100644 index 0000000000..132c64b837 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsSpi.h @@ -0,0 +1,119 @@ +/** + +Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchRegsSpi.h + + @brief + Register names for PCH SPI device. + + Conventions: + + - Prefixes: + 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 + - In general, PCH registers are denoted by "_PCH_" in register names + - Registers / bits that are different between PCH generations are denoted by + "_PCH__" in register/bit names. e.g., "_PCH_VLV_" + - Registers / bits that are different between SKUs are denoted by "_" + at the end of the register/bit names + - Registers / bits of new devices introduced in a PCH generation will be just named + as "_PCH_" without inserted. + +**/ +#ifndef _PCH_REGS_SPI_H_ +#define _PCH_REGS_SPI_H_ + +/// +/// SPI Host Interface Registers +/// + +#define R_PCH_SPI_HSFS 0x04 // Hardware Sequencing Flash Status Register (16bits) +#define B_PCH_SPI_HSFS_FLOCKDN BIT15 // Flash Configuration Lock-Down +#define B_PCH_SPI_HSFS_FDV BIT14 // Flash Descriptor Valid +#define B_PCH_SPI_HSFS_FDOPSS BIT13 // Flash Descriptor Override Pin-Strap Status +#define B_PCH_SPI_HSFS_SCIP BIT5 // SPI Cycle in Progress +#define B_PCH_SPI_HSFS_BERASE_MASK (BIT4 | BIT3) // Block / Sector Erase Size +#define V_PCH_SPI_HSFS_BERASE_256B 0x00 // Block/Sector = 256 Bytes +#define V_PCH_SPI_HSFS_BERASE_4K 0x01 // Block/Sector = 4K Bytes +#define V_PCH_SPI_HSFS_BERASE_8K 0x10 // Block/Sector = 8K Bytes +#define V_PCH_SPI_HSFS_BERASE_64K 0x11 // Block/Sector = 64K Bytes +#define B_PCH_SPI_HSFS_AEL BIT2 // Access Error Log +#define B_PCH_SPI_HSFS_FCERR BIT1 // Flash Cycle Error +#define B_PCH_SPI_HSFS_FDONE BIT0 // Flash Cycle Done + +#define R_PCH_SPI_PR0 0x74 // Protected Region 0 Register +#define B_PCH_SPI_PR0_WPE BIT31 // Write Protection Enable +#define B_PCH_SPI_PR0_PRL_MASK 0x1FFF0000 // Protected Range Limit Mask, [28:16] here represents upper limit of address [24:12] +#define B_PCH_SPI_PR0_RPE BIT15 // Read Protection Enable +#define B_PCH_SPI_PR0_PRB_MASK 0x00001FFF // Protected Range Base Mask, [12:0] here represents base limit of address [24:12] + +#define R_PCH_SPI_PREOP 0x94 // Prefix Opcode Configuration Register (16 bits) +#define B_PCH_SPI_PREOP1_MASK 0xFF00 // Prefix Opcode 1 Mask +#define B_PCH_SPI_PREOP0_MASK 0x00FF // Prefix Opcode 0 Mask + +#define R_PCH_SPI_OPTYPE 0x96 // Opcode Type Configuration +#define B_PCH_SPI_OPTYPE7_MASK (BIT15 | BIT14) // Opcode Type 7 Mask +#define B_PCH_SPI_OPTYPE6_MASK (BIT13 | BIT12) // Opcode Type 6 Mask +#define B_PCH_SPI_OPTYPE5_MASK (BIT11 | BIT10) // Opcode Type 5 Mask +#define B_PCH_SPI_OPTYPE4_MASK (BIT9 | BIT8) // Opcode Type 4 Mask +#define B_PCH_SPI_OPTYPE3_MASK (BIT7 | BIT6) // Opcode Type 3 Mask +#define B_PCH_SPI_OPTYPE2_MASK (BIT5 | BIT4) // Opcode Type 2 Mask +#define B_PCH_SPI_OPTYPE1_MASK (BIT3 | BIT2) // Opcode Type 1 Mask +#define B_PCH_SPI_OPTYPE0_MASK (BIT1 | BIT0) // Opcode Type 0 Mask +#define V_PCH_SPI_OPTYPE_RDNOADDR 0x00 // Read cycle type without address +#define V_PCH_SPI_OPTYPE_WRNOADDR 0x01 // Write cycle type without address +#define V_PCH_SPI_OPTYPE_RDADDR 0x02 // Address required; Read cycle type +#define V_PCH_SPI_OPTYPE_WRADDR 0x03 // Address required; Write cycle type + +#define R_PCH_SPI_OPMENU0 0x98 // Opcode Menu Configuration 0 (32bits) +#define R_PCH_SPI_OPMENU1 0x9C // Opcode Menu Configuration 1 (32bits) + +#define R_PCH_SPI_IND_LOCK 0xA4 // Indvidual Lock +#define B_PCH_SPI_IND_LOCK_PR0 BIT2 // PR0 LockDown + + +#define R_PCH_SPI_FDOC 0xB0 // Flash Descriptor Observability Control Register (32 bits) +#define B_PCH_SPI_FDOC_FDSS_MASK (BIT14 | BIT13 | BIT12) // Flash Descriptor Section Select +#define V_PCH_SPI_FDOC_FDSS_FSDM 0x0000 // Flash Signature and Descriptor Map +#define V_PCH_SPI_FDOC_FDSS_COMP 0x1000 // Component +#define V_PCH_SPI_FDOC_FDSS_REGN 0x2000 // Region +#define V_PCH_SPI_FDOC_FDSS_MSTR 0x3000 // Master +#define V_PCH_SPI_FDOC_FDSS_VLVS 0x4000 // Soft Straps +#define B_PCH_SPI_FDOC_FDSI_MASK 0x0FFC // Flash Descriptor Section Index + +#define R_PCH_SPI_FDOD 0xB4 // Flash Descriptor Observability Data Register (32 bits) + +#define R_PCH_SPI_BCR 0xFC // BIOS Control Register +#define S_PCH_SPI_BCR 1 +#define B_PCH_SPI_BCR_SMM_BWP BIT5 // SMM BIOS Write Protect Disable +#define B_PCH_SPI_BCR_SRC (BIT3 | BIT2) // SPI Read Configuration (SRC) +#define V_PCH_SPI_BCR_SRC_PREF_EN_CACHE_EN 0x08 // Prefetch Enable, Cache Enable +#define V_PCH_SPI_BCR_SRC_PREF_DIS_CACHE_DIS 0x04 // Prefetch Disable, Cache Disable +#define V_PCH_SPI_BCR_SRC_PREF_DIS_CACHE_EN 0x00 // Prefetch Disable, Cache Enable +#define B_PCH_SPI_BCR_BLE BIT1 // Lock Enable (LE) +#define B_PCH_SPI_BCR_BIOSWE BIT0 // Write Protect Disable (WPD) +#define N_PCH_SPI_BCR_BLE 1 +#define N_PCH_SPI_BCR_BIOSWE 0 + +// +// Flash Descriptor Base Address Region (FDBAR) from Flash Region 0 +// +#define R_PCH_SPI_FDBAR_FLVALSIG 0x00 // Flash Valid Signature +#define V_PCH_SPI_FDBAR_FLVALSIG 0x0FF0A55A + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsUsb.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsUsb.h new file mode 100644 index 0000000000..ccc41a5909 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/PchRegs/PchRegsUsb.h @@ -0,0 +1,98 @@ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchRegsUsb.h + + @brief + Register names for PCH USB devices. + + Conventions: + + - Prefixes: + 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 + - In general, PCH registers are denoted by "_PCH_" in register names + - Registers / bits that are different between PCH generations are denoted by + "_PCH__" in register/bit names. e.g., "_PCH_VLV_" + - Registers / bits that are different between SKUs are denoted by "_" + at the end of the register/bit names + - Registers / bits of new devices introduced in a PCH generation will be just named + as "_PCH_" without inserted. + +**/ +#ifndef _PCH_REGS_USB_H_ +#define _PCH_REGS_USB_H_ + +/// +/// USB Definitions +/// + +typedef enum { + PchEhci1 = 0, + PchEhciControllerMax +} PCH_USB20_CONTROLLER_TYPE; + +#define PCH_USB_MAX_PHYSICAL_PORTS 4 /// Max Physical Connector EHCI + XHCI, not counting virtual ports like USB-R. +#define PCH_EHCI_MAX_PORTS 4 /// Counting ports behind RMHs 8 from EHCI-1 and 6 from EHCI-2, not counting EHCI USB-R virtual ports. +#define PCH_HSIC_MAX_PORTS 2 +#define PCH_XHCI_MAX_USB3_PORTS 1 + +#define PCI_DEVICE_NUMBER_PCH_USB 29 +#define PCI_FUNCTION_NUMBER_PCH_EHCI 0 + +#define R_PCH_USB_VENDOR_ID 0x00 // Vendor ID +#define V_PCH_USB_VENDOR_ID V_PCH_INTEL_VENDOR_ID + +#define R_PCH_USB_DEVICE_ID 0x02 // Device ID +#define V_PCH_USB_DEVICE_ID_0 0x0F34 // EHCI#1 + +#define R_PCH_EHCI_SVID 0x2C // USB2 Subsystem Vendor ID +#define B_PCH_EHCI_SVID 0xFFFF // USB2 Subsystem Vendor ID Mask + +#define R_PCH_EHCI_PWR_CNTL_STS 0x54 // Power Management Control / Status +#define B_PCH_EHCI_PWR_CNTL_STS_PME_STS BIT15 // PME Status +#define B_PCH_EHCI_PWR_CNTL_STS_DATASCL (BIT14 | BIT13) // Data Scale +#define B_PCH_EHCI_PWR_CNTL_STS_DATASEL (BIT12 | BIT11 | BIT10 | BIT9) // Data Select +#define B_PCH_EHCI_PWR_CNTL_STS_PME_EN BIT8 // Power Enable +#define B_PCH_EHCI_PWR_CNTL_STS_PWR_STS (BIT1 | BIT0) // Power State +#define V_PCH_EHCI_PWR_CNTL_STS_PWR_STS_D0 0 // D0 State +#define V_PCH_EHCI_PWR_CNTL_STS_PWR_STS_D3 (BIT1 | BIT0) // D3 Hot State + +/// +/// USB3 (XHCI) related definitions +/// +#define PCI_DEVICE_NUMBER_PCH_XHCI 20 +#define PCI_FUNCTION_NUMBER_PCH_XHCI 0 +// +///// +///// XHCI PCI Config Space registers +///// + +#define R_PCH_XHCI_SVID 0x2C +#define B_PCH_XHCI_SVID 0xFFFF + + +#define R_PCH_XHCI_PWR_CNTL_STS 0x74 +#define B_PCH_XHCI_PWR_CNTL_STS_PME_STS BIT15 +#define B_PCH_XHCI_PWR_CNTL_STS_DATASCL (BIT14 | BIT13) +#define B_PCH_XHCI_PWR_CNTL_STS_DATASEL (BIT12 | BIT11 | BIT10 | BIT9) +#define B_PCH_XHCI_PWR_CNTL_STS_PME_EN BIT8 +#define B_PCH_XHCI_PWR_CNTL_STS_PWR_STS (BIT1 | BIT0) +#define V_PCH_XHCI_PWR_CNTL_STS_PWR_STS_D3 (BIT1 | BIT0) + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchInit.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchInit.h new file mode 100644 index 0000000000..3e90a12426 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchInit.h @@ -0,0 +1,81 @@ +/** +**/ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchInit.h + + @brief + This file defines the PCH Init PPI + +**/ +#ifndef _PCH_INIT_H_ +#define _PCH_INIT_H_ + +// +// Define the PCH Init PPI GUID +// + + +#include +#define PCH_INIT_PPI_GUID \ + { \ + 0x9ea894a, 0xbe0d, 0x4230, 0xa0, 0x3, 0xed, 0xc6, 0x93, 0xb4, 0x8e, 0x95 \ + } +extern EFI_GUID gPchInitPpiGuid; + +/// +/// Forward reference for ANSI C compatibility +/// +typedef struct _PCH_INIT_PPI PCH_INIT_PPI; + +/// +/// Data structure definitions +/// +typedef enum _CPU_STRAP_OPERATION { + GetCpuStrapSetData, + SetCpuStrapSetData, + LockCpuStrapSetData +} CPU_STRAP_OPERATION; + +typedef +EFI_STATUS +(EFIAPI *PCH_USB_INIT) ( + IN EFI_PEI_SERVICES **PeiServices + ) +/** + + @brief + The function performing USB init in PEI phase. This could be used by USB recovery + or debug features that need USB initialization during PEI phase. + Note: Before executing this function, please be sure that PCH_INIT_PPI.Initialize + has been done and PchUsbPolicyPpi has been installed. + + @param[in] PeiServices General purpose services available to every PEIM + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT. + +**/ +; + +/// +/// PCH_INIT_PPI Structure Definition +/// +struct _PCH_INIT_PPI { + PCH_USB_INIT UsbInit; +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchPeiInit.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchPeiInit.h new file mode 100644 index 0000000000..81995cf5a5 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchPeiInit.h @@ -0,0 +1,40 @@ + +/*++ + +Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + PchPeiInit.h + +Abstract: + + +--*/ + +#ifndef _PCH_PEI_INIT_H_ +#define _PCH_PEI_INIT_H_ + +// +// Define the PCH PEI Init PPI GUID +// +#define PCH_PEI_INIT_PPI_GUID \ + { \ + 0xACB93B08, 0x5CDC, 0x4A8F, 0x93, 0xD4, 0x6, 0xE3, 0x42, 0xDF, 0x18, 0x2E \ + } + +// +// Extern the GUID for PPI users. +// +extern EFI_GUID gPchPeiInitPpiGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchPlatformPolicy.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchPlatformPolicy.h new file mode 100644 index 0000000000..f2f444c77b --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchPlatformPolicy.h @@ -0,0 +1,167 @@ +/** +**/ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchPlatformPolicy.h + + @brief + PCH policy PPI produced by a platform driver specifying various + expected PCH settings. This PPI is consumed by the PCH PEI modules. + +**/ +#ifndef PCH_PLATFORM_POLICY_H_ +#define PCH_PLATFORM_POLICY_H_ +// +// External include files do NOT need to be explicitly specified in real EDKII +// environment +// + + +#include "PchRegs.h" + +// +#define PCH_PLATFORM_POLICY_PPI_GUID \ + { \ + 0x15344673, 0xd365, 0x4be2, 0x85, 0x13, 0x14, 0x97, 0xcc, 0x7, 0x61, 0x1d \ + } + +extern EFI_GUID gPchPlatformPolicyPpiGuid; + +/// +/// Forward reference for ANSI C compatibility +/// +typedef struct _PCH_PLATFORM_POLICY_PPI PCH_PLATFORM_POLICY_PPI; + +/// +/// PPI revision number +/// Any backwards compatible changes to this PPI will result in an update in the revision number +/// Major changes will require publication of a new PPI +/// +/// Revision 1: Original version +/// +#define PCH_PLATFORM_POLICY_PPI_REVISION_1 1 +#define PCH_PLATFORM_POLICY_PPI_REVISION_2 2 +#define PCH_PLATFORM_POLICY_PPI_REVISION_3 3 +#define PCH_PLATFORM_POLICY_PPI_REVISION_4 4 +#define PCH_PLATFORM_POLICY_PPI_REVISION_5 5 +// +// Generic definitions for device enabling/disabling used by PCH code. +// +#define PCH_DEVICE_ENABLE 1 +#define PCH_DEVICE_DISABLE 0 + +typedef struct { + UINT8 ThermalDataReportEnable : 1; // OBSOLETE from Revision 5 !!! DO NOT USE !!! + UINT8 MchTempReadEnable : 1; + UINT8 PchTempReadEnable : 1; + UINT8 CpuEnergyReadEnable : 1; + UINT8 CpuTempReadEnable : 1; + UINT8 Cpu2TempReadEnable : 1; + UINT8 TsOnDimmEnable : 1; + UINT8 Dimm1TempReadEnable : 1; + + UINT8 Dimm2TempReadEnable : 1; + UINT8 Dimm3TempReadEnable : 1; + UINT8 Dimm4TempReadEnable : 1; + UINT8 Rsvdbits : 5; +} PCH_THERMAL_REPORT_CONTROL; +// +// ---------------------------- HPET Config ----------------------------- +// +typedef struct { + BOOLEAN Enable; /// Determines if enable HPET function + UINT32 Base; /// The HPET base address +} PCH_HPET_CONFIG; + + +/// +/// ---------------------------- SATA Config ----------------------------- +/// +typedef enum { + PchSataModeIde, + PchSataModeAhci, + PchSataModeRaid, + PchSataModeMax +} PCH_SATA_MODE; + +/// +/// ---------------------------- PCI Express Config ----------------------------- +/// +typedef enum { + PchPcieAuto, + PchPcieGen1, + PchPcieGen2 +} PCH_PCIE_SPEED; + +typedef struct { + PCH_PCIE_SPEED PcieSpeed[PCH_PCIE_MAX_ROOT_PORTS]; +} PCH_PCIE_CONFIG; + +/// +/// ---------------------------- IO APIC Config ----------------------------- +/// +typedef struct { + UINT8 IoApicId; +} PCH_IOAPIC_CONFIG; + +/// +/// --------------------- Low Power Input Output Config ------------------------ +/// +typedef struct { + UINT8 LpssPciModeEnabled : 1; /// Determines if LPSS PCI Mode enabled + UINT8 Dma0Enabled : 1; /// Determines if LPSS DMA1 enabled + UINT8 Dma1Enabled : 1; /// Determines if LPSS DMA2 enabled + UINT8 I2C0Enabled : 1; /// Determines if LPSS I2C #1 enabled + UINT8 I2C1Enabled : 1; /// Determines if LPSS I2C #2 enabled + UINT8 I2C2Enabled : 1; /// Determines if LPSS I2C #3 enabled + UINT8 I2C3Enabled : 1; /// Determines if LPSS I2C #4 enabled + UINT8 I2C4Enabled : 1; /// Determines if LPSS I2C #5 enabled + UINT8 I2C5Enabled : 1; /// Determines if LPSS I2C #6 enabled + UINT8 I2C6Enabled : 1; /// Determines if LPSS I2C #7 enabled + UINT8 Pwm0Enabled : 1; /// Determines if LPSS PWM #1 enabled + UINT8 Pwm1Enabled : 1; /// Determines if LPSS PWM #2 enabled + UINT8 Hsuart0Enabled : 1; /// Determines if LPSS HSUART #1 enabled + UINT8 Hsuart1Enabled : 1; /// Determines if LPSS HSUART #2 enabled + UINT8 SpiEnabled : 1; /// Determines if LPSS SPI enabled + UINT8 Rsvdbits : 2; +} PEI_PCH_LPSS_CONFIG; + +/// +/// ------------ General PCH Platform Policy PPI definition ------------ +/// +struct _PCH_PLATFORM_POLICY_PPI { + UINT8 Revision; + UINT8 BusNumber; // Bus Number of the PCH device + UINT32 SpiBase; // SPI Base Address. + UINT32 PmcBase; // PMC Base Address. + UINT32 SmbmBase; // SMB Memory Base Address. + UINT32 IoBase; // IO Base Address. + UINT32 IlbBase; // Intel Legacy Block Base Address. + UINT32 PUnitBase; // PUnit Base Address. + UINT32 Rcba; // Root Complex Base Address. + UINT32 MphyBase; // MPHY Base Address. + UINT16 AcpiBase; // ACPI I/O Base address. + UINT16 GpioBase; // GPIO Base address + PCH_HPET_CONFIG *HpetConfig; + PCH_SATA_MODE SataMode; + PCH_PCIE_CONFIG *PcieConfig; + PCH_IOAPIC_CONFIG *IoApicConfig; + PEI_PCH_LPSS_CONFIG *LpssConfig; + BOOLEAN EnableRmh; // Determines if enable USB RMH function + BOOLEAN EhciPllCfgEnable; +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchUsbPolicy.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchUsbPolicy.h new file mode 100644 index 0000000000..41c2b48263 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PchUsbPolicy.h @@ -0,0 +1,75 @@ +/** +**/ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchUsbPolicy.h + + @brief + PCH Usb policy PPI produced by a platform driver specifying + various expected PCH Usb settings. This PPI is consumed by the + PCH PEI drivers. + +**/ +#ifndef _PCH_USB_POLICY_H_ +#define _PCH_USB_POLICY_H_ + +// +// PCH Usb policy provided by platform for PEI phase +// + +#ifndef ECP_FLAG +#include +#endif + +#include "PchRegs.h" +#include + +#define PCH_USB_POLICY_PPI_GUID \ + { \ + 0xc02b0573, 0x2b4e, 0x4a31, 0xa3, 0x1a, 0x94, 0x56, 0x7b, 0x50, 0x44, 0x2c \ + } + +extern EFI_GUID gPchUsbPolicyPpiGuid; + +typedef struct _PCH_USB_POLICY_PPI PCH_USB_POLICY_PPI; + +/// +/// PPI revision number +/// Any backwards compatible changes to this PPI will result in an update in the revision number +/// Major changes will require publication of a new PPI +/// +/// Revision 1: Original version +/// +#define PCH_USB_POLICY_PPI_REVISION_1 1 + +/// +/// Generic definitions for device enabling/disabling used by PCH code. +/// +#define PCH_DEVICE_ENABLE 1 +#define PCH_DEVICE_DISABLE 0 + +#define EHCI_MODE 1 + +struct _PCH_USB_POLICY_PPI { + UINT8 Revision; + PCH_USB_CONFIG *UsbConfig; + UINT8 Mode; + UINTN EhciMemBaseAddr; + UINT32 EhciMemLength; + UINTN XhciMemBaseAddr; +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PeiBlockIo.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PeiBlockIo.h new file mode 100644 index 0000000000..16a137f151 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/PeiBlockIo.h @@ -0,0 +1,236 @@ +/** @file + Block IO protocol as defined in the UEFI 2.0 specification. + + The Block IO protocol is used to abstract block devices like hard drives, + DVD-ROMs and floppy drives. + + Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PEI_BLOCK_IO_H__ +#define __PEI_BLOCK_IO_H__ +// {BC5FA650-EDBB-4d0d-B3A3-D98907F847DF} +#ifndef ECP_FLAG +#define PEI_BLOCK_IO_PPI_GUID \ + { \ + 0xbc5fa650, 0xedbb, 0x4d0d, { 0xb3, 0xa3, 0xd9, 0x89, 0x7, 0xf8, 0x47, 0xdf } \ + } +#endif +typedef struct _PEI_BLOCK_IO_PPI PEI_BLOCK_IO_PPI; + + +/** + Reset the Block Device. + + @param This Indicates a pointer to the calling context. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *PEI_BLOCK_RESET)( + IN PEI_BLOCK_IO_PPI *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Read BufferSize bytes from Lba into Buffer. + + @param This Indicates a pointer to the calling context. + @param MediaId Id of the media, changes every time the media is replaced. + @param Lba The starting Logical Block Address to read from + @param BufferSize Size of Buffer, must be a multiple of device block size. + @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 The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while performing the read. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the buffer is not on proper alignment. + +**/ +typedef +EFI_STATUS +(EFIAPI *PEI_BLOCK_READ)( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_BLOCK_IO_PPI *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Write BufferSize bytes from Lba into Buffer. + + @param This Indicates a pointer to the calling context. + @param MediaId The media ID that the write request is for. + @param Lba The starting logical block address to be written. The caller is + responsible for writing to only legitimate locations. + @param BufferSize Size of Buffer, must be a multiple of device block size. + @param Buffer A pointer to the source buffer for the data. + + @retval EFI_SUCCESS The data was written correctly to the device. + @retval EFI_WRITE_PROTECTED The device can not be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the buffer is not on proper alignment. + +**/ +typedef +EFI_STATUS +(EFIAPI *PEI_BLOCK_WRITE)( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_BLOCK_IO_PPI *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + Flush the Block Device. + + @param This Indicates a pointer to the calling context. + + @retval EFI_SUCCESS All outstanding data was written to the device + @retval EFI_DEVICE_ERROR The device reported an error while writting back the data + @retval EFI_NO_MEDIA There is no media in the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *PEI_BLOCK_FLUSH)( + IN PEI_BLOCK_IO_PPI *This + ); + +/** + Block IO read only mode data and updated only via members of BlockIO +**/ +typedef struct { + /// + /// The curent media Id. If the media changes, this value is changed. + /// + UINT32 MediaId; + + /// + /// TRUE if the media is removable; otherwise, FALSE. + /// + BOOLEAN RemovableMedia; + + /// + /// TRUE if there is a media currently present in the device; + /// othersise, FALSE. THis field shows the media present status + /// as of the most recent ReadBlocks() or WriteBlocks() call. + /// + BOOLEAN MediaPresent; + + /// + /// TRUE if LBA 0 is the first block of a partition; otherwise + /// FALSE. For media with only one partition this would be TRUE. + /// + BOOLEAN LogicalPartition; + + /// + /// TRUE if the media is marked read-only otherwise, FALSE. + /// This field shows the read-only status as of the most recent WriteBlocks () call. + /// + BOOLEAN ReadOnly; + + /// + /// TRUE if the WriteBlock () function caches write data. + /// + BOOLEAN WriteCaching; + + /// + /// The intrinsic block size of the device. If the media changes, then + /// this field is updated. + /// + UINT32 BlockSize; + + /// + /// Supplies the alignment requirement for any buffer to read or write block(s). + /// + UINT32 IoAlign; + + /// + /// The last logical block address on the device. + /// If the media changes, then this field is updated. + /// + EFI_LBA LastBlock; + + /// + /// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to + /// EFI_BLOCK_IO_PROTOCOL_REVISION2. Returns the first LBA is aligned to + /// a physical block boundary. + /// + EFI_LBA LowestAlignedLba; + + /// + /// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to + /// EFI_BLOCK_IO_PROTOCOL_REVISION2. Returns the number of logical blocks + /// per physical block. + /// + UINT32 LogicalBlocksPerPhysicalBlock; + + /// + /// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to + /// EFI_BLOCK_IO_PROTOCOL_REVISION3. Returns the optimal transfer length + /// granularity as a number of logical blocks. + /// + UINT32 OptimalTransferLengthGranularity; +#ifdef ECP_FLAG +} PEI_BLOCK_IO_MEDIA2; +#else +} PEI_BLOCK_IO_MEDIA; +#endif +#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000 +#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001 +#define EFI_BLOCK_IO_PROTOCOL_REVISION3 0x00020031 + +/// +/// Revision defined in EFI1.1. +/// +#define EFI_BLOCK_IO_INTERFACE_REVISION EFI_BLOCK_IO_PROTOCOL_REVISION + +/// +/// This protocol provides control over block devices. +/// +struct _PEI_BLOCK_IO_PPI { + /// + /// The revision to which the block IO interface adheres. All future + /// revisions must be backwards compatible. If a future version is not + /// back wards compatible, it is not the same GUID. + /// + UINT64 Revision; + /// + /// Pointer to the EFI_BLOCK_IO_MEDIA data for this device. + /// + PEI_BLOCK_IO_MEDIA *Media; + PEI_BLOCK_RESET Reset; + PEI_BLOCK_READ ReadBlocks; + PEI_BLOCK_WRITE WriteBlocks; + PEI_BLOCK_FLUSH FlushBlocks; +}; + +//extern EFI_GUID gEfiBlockIoProtocolGuid; +extern EFI_GUID gPeiBlockIoPpiGuid; +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/Sdhc.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/Sdhc.h new file mode 100644 index 0000000000..2239959e8f --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/Sdhc.h @@ -0,0 +1,365 @@ +/** +**/ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + Spi.h + + @brief + This file defines the EFI SPI PPI which implements the + Intel(R) PCH SPI Host Controller Compatibility Interface. + +**/ +#ifndef _PEI_SDHC_H_ +#define _PEI_SDHC_H_ + + + +// +#define PEI_SDHC_PPI_GUID \ + { \ + 0xf4ef9d7a, 0x98c5, 0x4c1a, 0xb4, 0xd9, 0xd8, 0xd8, 0x72, 0x65, 0xbe, 0xc \ + } +typedef struct _PEI_SD_CONTROLLER_PPI PEI_SD_CONTROLLER_PPI; + +#define EFI_SD_HOST_IO_PROTOCOL_REVISION_01 0x01 + +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; + + + +typedef enum { + SDMA = 0, + ADMA2, + PIO +} DMA_MOD; + +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: 4; + UINT32 BusWidth4: 1; // 4 bit width + UINT32 BusWidth8: 1; // 8 bit width + UINT32 Reserved1: 6; + UINT32 SDMASupport: 1; + UINT32 ADMA2Support: 1; + UINT32 DmaMode: 2; + UINT32 Reserved2: 12; + UINT32 BoundarySize; +}HOST_CAPABILITY; + + +#define PCI_SUBCLASS_SD_HOST_CONTROLLER 0x05 +#define PCI_IF_STANDARD_HOST_NO_DMA 0x00 +#define PCI_IF_STANDARD_HOST_SUPPORT_DMA 0x01 + +// +//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 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_HOST_CTL2 0x3E //hphang <- New in VLV2 +#define MMIO_CAP 0x40 +#define MMIO_CAP2 0x44 //hphang <- New in VLV2 +#define MMIO_MCCAP 0x48 +#define MMIO_FORCEEVENTCMD12ERRSTAT 0x50 //hphang <- New in VLV2 +#define MMIO_FORCEEVENTERRINTSTAT 0x52 //hphang <- New in VLV2 +#define MMIO_ADMAERRSTAT 0x54 //hphang <- New in VLV2 +#define MMIO_ADMASYSADDR 0x58 //hphang <- New in VLV2 +#define MMIO_PRESETVALUE0 0x60 //hphang <- New in VLV2 +#define MMIO_PRESETVALUE1 0x64 //hphang <- New in VLV2 +#define MMIO_PRESETVALUE2 0x68 //hphang <- New in VLV2 +#define MMIO_PRESETVALUE3 0x6C //hphang <- New in VLV2 +#define MMIO_BOOTTIMEOUTCTRL 0x70 //hphang <- New in VLV2 +#define MMIO_DEBUGSEL 0x74 //hphang <- New in VLV2 +#define MMIO_SHAREDBUS 0xE0 //hphang <- New in VLV2 +#define MMIO_SPIINTSUP 0xF0 //hphang <- New in VLV2 +#define MMIO_SLTINTSTS 0xFC +#define MMIO_CTRLRVER 0xFE +#define MMIO_SRST 0x1FC + +typedef +EFI_STATUS +(EFIAPI *EFI_SD_CONTROLLER_PPI_SEND_COMMAND) ( + IN PEI_SD_CONTROLLER_PPI *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: + 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. + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + MaxFrequency - Max frequency in HZ + + Returns: + EFI_SUCCESS + EFI_TIMEOUT +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_CONTROLLER_PPI_SET_CLOCK_FREQUENCY) ( + IN PEI_SD_CONTROLLER_PPI *This, + IN UINT32 MaxFrequency + ); + +/*++ + + Routine Description: + Set bus width of the host + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + BusWidth - Bus width in 1, 4, 8 bits + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_CONTROLLER_PPI_SET_BUS_WIDTH) ( + IN PEI_SD_CONTROLLER_PPI *This, + IN UINT32 BusWidth + ); + +/*++ + + Routine Description: + Set Host mode in DDR + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + SetHostDdrMode - True for DDR Mode set, false for normal mode + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_HOST_DDR_MODE) ( + IN PEI_SD_CONTROLLER_PPI *This, + IN UINT32 DdrMode + ); + +/*++ + + Routine Description: + Set voltage which could supported by the host. + Support 0(Power off the host), 1.8V, 3.0V, 3.3V + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + Voltage - Units in 0.1 V + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_CONTROLLER_PPI_SET_HOST_VOLTAGE) ( + IN PEI_SD_CONTROLLER_PPI *This, + IN UINT32 Voltage + ); + +/*++ + + Routine Description: + Reset the host + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + ResetAll - TRUE to reset all + + Returns: + EFI_SUCCESS + EFI_TIMEOUT + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_CONTROLLER_PPI_RESET_SD_HOST) ( + IN PEI_SD_CONTROLLER_PPI *This, + IN RESET_TYPE ResetType + ); + +/*++ + + Routine Description: + Reset the host + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + Enable - TRUE to enable, FALSE to disable + + Returns: + EFI_SUCCESS + EFI_TIMEOUT + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_CONTROLLER_PPI_ENABLE_AUTO_STOP_CMD) ( + IN PEI_SD_CONTROLLER_PPI *This, + IN BOOLEAN Enable + ); + +/*++ + + Routine Description: + Find whether these is a card inserted into the slot. If so + init the host. If not, return EFI_NOT_FOUND. + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + + Returns: + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_CONTROLLER_PPI_DETECT_CARD_AND_INIT_HOST) ( + IN PEI_SD_CONTROLLER_PPI *This + ); + +/*++ + + Routine Description: + Set the Block length + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + BlockLength - card supportes block length + + Returns: + EFI_SUCCESS + EFI_TIMEOUT + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_CONTROLLER_PPI_SET_BLOCK_LENGTH) ( + IN PEI_SD_CONTROLLER_PPI *This, + IN UINT32 BlockLength + ); + +/*++ + + Routine Description: + Set the Block length + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + BlockLength - card supportes block length + + Returns: + EFI_SUCCESS + EFI_TIMEOUT + +--*/ + +typedef EFI_STATUS +(EFIAPI *EFI_SD_CONTROLLER_PPI_SETUP_DEVICE)( + IN PEI_SD_CONTROLLER_PPI *This + ); + +// +// Interface structure for the EFI SD Host I/O Protocol +// +struct _PEI_SD_CONTROLLER_PPI { + UINT32 Revision; + HOST_CAPABILITY HostCapability; + EFI_SD_CONTROLLER_PPI_SEND_COMMAND SendCommand; + EFI_SD_CONTROLLER_PPI_SET_CLOCK_FREQUENCY SetClockFrequency; + EFI_SD_CONTROLLER_PPI_SET_BUS_WIDTH SetBusWidth; + EFI_SD_CONTROLLER_PPI_SET_HOST_VOLTAGE SetHostVoltage; + EFI_SD_HOST_IO_PROTOCOL_SET_HOST_DDR_MODE SetHostDdrMode; + EFI_SD_CONTROLLER_PPI_RESET_SD_HOST ResetSdHost; + EFI_SD_CONTROLLER_PPI_ENABLE_AUTO_STOP_CMD EnableAutoStopCmd; + EFI_SD_CONTROLLER_PPI_DETECT_CARD_AND_INIT_HOST DetectCardAndInitHost; + EFI_SD_CONTROLLER_PPI_SET_BLOCK_LENGTH SetBlockLength; + EFI_SD_CONTROLLER_PPI_SETUP_DEVICE SetupDevice; +}; +// Extern the GUID for PPI users. +// +extern EFI_GUID gPeiSdhcPpiGuid; + + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/SmbusPolicy.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/SmbusPolicy.h new file mode 100644 index 0000000000..c4eba99449 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/SmbusPolicy.h @@ -0,0 +1,46 @@ +// +// + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + SmbusPolicy.h + +Abstract: + + Smbus Policy PPI as defined in EFI 2.0 + +--*/ +#ifndef _PEI_SMBUS_POLICY_PPI_H +#define _PEI_SMBUS_POLICY_PPI_H + +#define PEI_SMBUS_POLICY_PPI_GUID \ + { \ + 0x63b6e435, 0x32bc, 0x49c6, 0x81, 0xbd, 0xb7, 0xa1, 0xa0, 0xfe, 0x1a, 0x6c \ + } + +typedef struct _PEI_SMBUS_POLICY_PPI PEI_SMBUS_POLICY_PPI; + +typedef struct _PEI_SMBUS_POLICY_PPI { + UINTN BaseAddress; + UINT32 PciAddress; + UINT8 NumRsvdAddress; + UINT8 *RsvdAddress; +} PEI_SMBUS_POLICY_PPI; + +extern EFI_GUID gPeiSmbusPolicyPpiGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/Spi.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/Spi.h new file mode 100644 index 0000000000..7c8afec0bf --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Ppi/Spi.h @@ -0,0 +1,48 @@ +/** +**/ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + Spi.h + + @brief + This file defines the EFI SPI PPI which implements the + Intel(R) PCH SPI Host Controller Compatibility Interface. + +**/ +#ifndef _PEI_SPI_H_ +#define _PEI_SPI_H_ + + +#include + + +// +#define PEI_SPI_PPI_GUID \ + { \ + 0xa38c6898, 0x2b5c, 0x4ff6, 0x93, 0x26, 0x2e, 0x63, 0x21, 0x2e, 0x56, 0xc2 \ + } +// Extern the GUID for PPI users. +// +extern EFI_GUID gPeiSpiPpiGuid; + +/// +/// Reuse the EFI_SPI_PROTOCOL definitions +/// This is possible becaues the PPI implementation does not rely on a PeiService pointer, +/// as it uses EDKII Glue Lib to do IO accesses +/// +typedef EFI_SPI_PROTOCOL PEI_SPI_PPI; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/ActiveBios.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/ActiveBios.h new file mode 100644 index 0000000000..4f45d8b661 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/ActiveBios.h @@ -0,0 +1,129 @@ +/** +**/ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + ActiveBios.h + + @brief + This protocol is used to report and control what BIOS is mapped to the + BIOS address space anchored at 4GB boundary. + + This protocol is EFI compatible. + + E.G. For current generation ICH, the 4GB-16MB to 4GB range can be mapped + to PCI, SPI, or FWH. + +**/ +#ifndef _EFI_ACTIVE_BIOS_PROTOCOL_H_ +#define _EFI_ACTIVE_BIOS_PROTOCOL_H_ + + + + +// +#define EFI_ACTIVE_BIOS_PROTOCOL_GUID \ + { \ + 0xebbe2d1b, 0x1647, 0x4bda, 0xab, 0x9a, 0x78, 0x63, 0xe3, 0x96, 0xd4, 0x1a \ + } +extern EFI_GUID gEfiActiveBiosProtocolGuid; + +/// +/// Forward reference for ANSI C compatibility +/// +typedef struct _EFI_ACTIVE_BIOS_PROTOCOL EFI_ACTIVE_BIOS_PROTOCOL; + +/// +/// Protocol definitions +/// +typedef enum { + ActiveBiosStateSpi, + ActiveBiosStatePci, /// Obsolete since VLV + ActiveBiosStateLpc, + ActiveBiosStateMax +} EFI_ACTIVE_BIOS_STATE; + +typedef +EFI_STATUS +(EFIAPI *EFI_ACTIVE_BIOS_SET_ACTIVE_BIOS_STATE) ( + IN EFI_ACTIVE_BIOS_PROTOCOL * This, + IN EFI_ACTIVE_BIOS_STATE DesiredState, + IN UINTN Key + ) +/** + + @brief + Change the current active BIOS settings to the requested state. + The caller is responsible for requesting a supported state from + the EFI_ACTIVE_BIOS_STATE selections. + This will fail if someone has locked the interface and the correct key is + not provided. + + @param[in] This Pointer to the EFI_ACTIVE_BIOS_PROTOCOL instance. + @param[in] DesiredState The requested state to configure the system for. + @param[in] Key If the interface is locked, Key must be the Key + returned from the LockState function call. + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_ACCESS_DENIED The interface is currently locked. + +**/ +; + +typedef +EFI_STATUS +(EFIAPI *EFI_ACTIVE_BIOS_LOCK_ACTIVE_BIOS_STATE) ( + IN EFI_ACTIVE_BIOS_PROTOCOL * This, + IN BOOLEAN Lock, + IN OUT UINTN *Key + ); + +/** + + @brief + Lock the current active BIOS state from further changes. This allows a + caller to implement a critical section. This is optionally supported + functionality. Size conscious implementations may choose to require + callers cooperate without support from this protocol. + + @param[in] This Pointer to the EFI_ACTIVE_BIOS_PROTOCOL instance. + @param[in] Lock TRUE to lock the current state, FALSE to unlock. + @param[in] Key If Lock is TRUE, then a key will be returned. If + Lock is FALSE, the key returned from the prior call + to lock the protocol must be provided to unlock the + protocol. The value of Key is undefined except that + it cannot be 0. + + @retval EFI_SUCCESS Command succeed. + @exception EFI_UNSUPPORTED The function is not supported. + @retval EFI_ACCESS_DENIED The interface is currently locked. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. + +**/ + +/// +/// Protocol definition +/// +/// Note that some functions are optional. This means that they may be NULL. +/// Caller is required to verify that an optional function is defined by checking +/// that the value is not NULL. +/// +struct _EFI_ACTIVE_BIOS_PROTOCOL { + EFI_ACTIVE_BIOS_STATE State; + EFI_ACTIVE_BIOS_SET_ACTIVE_BIOS_STATE SetState; + EFI_ACTIVE_BIOS_LOCK_ACTIVE_BIOS_STATE LockState; +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/ActiveBiosProtocol.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/ActiveBiosProtocol.h new file mode 100644 index 0000000000..e59cfc09f5 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/ActiveBiosProtocol.h @@ -0,0 +1,131 @@ +/** + This protocol is used to report and control what BIOS is mapped to the + BIOS address space anchored at 4GB boundary. + + This protocol is EFI compatible. + + E.G. For current generation ICH, the 4GB-16MB to 4GB range can be mapped + to PCI, SPI, or FWH. + +Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + + +#ifndef _EFI_ACTIVE_BIOS_PROTOCOL_H_ +#define _EFI_ACTIVE_BIOS_PROTOCOL_H_ + +// +// Define the protocol GUID +// +#define EFI_ACTIVE_BIOS_PROTOCOL_GUID \ + { 0xebbe2d1b, 0x1647, 0x4bda, {0xab, 0x9a, 0x78, 0x63, 0xe3, 0x96, 0xd4, 0x1a} } + +typedef struct _EFI_ACTIVE_BIOS_PROTOCOL EFI_ACTIVE_BIOS_PROTOCOL; + +// +// Protocol definitions +// +typedef enum { + ActiveBiosStateSpi, + ActiveBiosStatePci, + ActiveBiosStateLpc, + ActiveBiosStateMax +} EFI_ACTIVE_BIOS_STATE; + +typedef +EFI_STATUS +(EFIAPI *EFI_ACTIVE_BIOS_SET_ACTIVE_BIOS_STATE) ( + IN EFI_ACTIVE_BIOS_PROTOCOL *This, + IN EFI_ACTIVE_BIOS_STATE DesiredState, + IN UINTN Key + ); +/*++ + +Routine Description: + + Change the current active BIOS settings to the requested state. + The caller is responsible for requesting a supported state from + the EFI_ACTIVE_BIOS_STATE selections. + + This will fail if someone has locked the interface and the correct key is + not provided. + +Arguments: + + This Pointer to the EFI_ACTIVE_BIOS_PROTOCOL instance. + DesiredState The requested state to configure the system for. + Key If the interface is locked, Key must be the Key + returned from the LockState function call. + +Returns: + + EFI_SUCCESS Command succeed. + EFI_ACCESS_DENIED The interface is currently locked. + EFI_DEVICE_ERROR Device error, command aborts abnormally. + +--*/ + +typedef +EFI_STATUS +(EFIAPI *EFI_ACTIVE_BIOS_LOCK_ACTIVE_BIOS_STATE) ( + IN EFI_ACTIVE_BIOS_PROTOCOL *This, + IN BOOLEAN Lock, + IN OUT UINTN *Key + ); +/*++ + +Routine Description: + + Lock the current active BIOS state from further changes. This allows a + caller to implement a critical section. This is optionally supported + functionality. Size conscious implementations may choose to require + callers cooperate without support from this protocol. + +Arguments: + + This Pointer to the EFI_ACTIVE_BIOS_PROTOCOL instance. + Lock TRUE to lock the current state, FALSE to unlock. + Key If Lock is TRUE, then a key will be returned. If + Lock is FALSE, the key returned from the prior call + to lock the protocol must be provided to unlock the + protocol. The value of Key is undefined except that it + will never be 0. + +Returns: + + EFI_SUCCESS Command succeed. + EFI_UNSUPPORTED The function is not supported. + EFI_ACCESS_DENIED The interface is currently locked. + EFI_DEVICE_ERROR Device error, command aborts abnormally. + +--*/ + +// +// Protocol definition +// +// Note that some functions are optional. This means that they may be NULL. +// Caller is required to verify that an optional function is defined by checking +// that the value is not NULL. +// +struct _EFI_ACTIVE_BIOS_PROTOCOL { + EFI_ACTIVE_BIOS_STATE State; + EFI_ACTIVE_BIOS_SET_ACTIVE_BIOS_STATE SetState; + EFI_ACTIVE_BIOS_LOCK_ACTIVE_BIOS_STATE LockState; +}; + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gEfiActiveBiosProtocolGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/DxePchPolicyUpdateProtocol.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/DxePchPolicyUpdateProtocol.h new file mode 100644 index 0000000000..25dbb502ac --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/DxePchPolicyUpdateProtocol.h @@ -0,0 +1,57 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + DxePchPolicyUpdateProtocol.h + +Abstract: + + PCH policy update protocol. This protocol is consumed by the PchDxePolicyInit driver + +--*/ +#ifndef _DXE_PCH_POLICY_UPDATE_PROTOCOL_H_ +#define _DXE_PCH_POLICY_UPDATE_PROTOCOL_H_ + +#include "PchRegs.h" + + +#ifdef ECP_FLAG +#define DXE_PCH_POLICY_UPDATE_PROTOCOL_GUID \ + { \ + 0x1a819e49, 0xd8ee, 0x48cb, 0x9a, 0x9c, 0xa, 0xa0, 0xd2, 0x81, 0xa, 0x38 \ + } +#else +#define DXE_PCH_POLICY_UPDATE_PROTOCOL_GUID \ + { \ + 0x1a819e49, 0xd8ee, 0x48cb, \ + { \ + 0x9a, 0x9c, 0xa, 0xa0, 0xd2, 0x81, 0xa, 0x38 \ + } \ + } +#endif + +extern EFI_GUID gDxePchPolicyUpdateProtocolGuid; +#define DXE_PCH_POLICY_UPDATE_PROTOCOL_REVISION_1 1 + +// +// ------------ General PCH policy Update protocol definition ------------ +// +struct _DXE_PCH_POLICY_UPDATE_PROTOCOL { + UINT8 Revision; +}; + +typedef struct _DXE_PCH_POLICY_UPDATE_PROTOCOL DXE_PCH_POLICY_UPDATE_PROTOCOL; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/EmmcCardInfoProtocol.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/EmmcCardInfoProtocol.h new file mode 100644 index 0000000000..718ddbcc7f --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/EmmcCardInfoProtocol.h @@ -0,0 +1,48 @@ +/*++ + +Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +--*/ + + +/*++ +Module Name: + + EmmcCardInfoProtocol.h + +Abstract: + + Interface definition for EFI_EMMC_CARD_INFO_PROTOCOL + +--*/ + + +#ifndef _EMMC_CARD_INFO_H_ +#define _EMMC_CARD_INFO_H_ + +#define EFI_EMMC_CARD_INFO_PROTOCOL_GUID \ + { \ + 0x1ebe5ab9, 0x2129, 0x49e7, {0x84, 0xd7, 0xee, 0xb9, 0xfc, 0xe5, 0xde, 0xdd } \ + } + +typedef struct _EFI_EMMC_CARD_INFO_PROTOCOL EFI_EMMC_CARD_INFO_PROTOCOL; + + +// +// EMMC Card info Structures +// +struct _EFI_EMMC_CARD_INFO_PROTOCOL { + CARD_DATA *CardData; +}; + +extern EFI_GUID gEfiEmmcCardInfoProtocolGuid; +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/Gpio.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/Gpio.h new file mode 100644 index 0000000000..030fb83d74 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/Gpio.h @@ -0,0 +1,167 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Gpio.h + +Abstract: + +EFI 2.0 PEIM to provide platform specific information to other +modules and to do some platform specific initialization. + +--*/ + +#ifndef _PEI_GPIO_H +#define _PEI_GPIO_H + +//#include "Efi.h" +//#include "EfiCommonLib.h" +//#include "Pei.h" +//#include "Numbers.h" + +//// +//// GPIO Register Settings for BeaverBridge (FFVS) (Cedarview/Tigerpoint) +//// +//// Field Descriptions: +//// USE: Defines the pin's usage model: GPIO (G) or Native (N) mode. +//// I/O: Defines whether GPIOs are inputs (I) or outputs (O). +//// (Note: Only meaningful for pins used as GPIOs.) +//// LVL: This field gives you the initial value for "output" GPIO's. +//// (Note: The output level is dependent upon whether the pin is inverted.) +//// INV: Defines whether Input GPIOs activation level is inverted. +//// (Note: Only affects the level sent to the GPE logic and does not +//// affect the level read through the GPIO registers.) +//// +//// Notes: +//// 1. BoardID is GPIO [8:38:34] +//// +////Signal UsedAs USE I/O LVL INV +////-------------------------------------------------------------------------- +////GPIO0 Nonfunction G O H - +////GPIO1 SMC_RUNTIME_SCI# G I - I +////PIRQE#/GPIO2 Nonfunction G O H - +////PIRQF#/GPIO3 Nonfunction G O H - +////PIRQG#/GPIO4 Nonfunction G O H - +////PIRQH#/GPIO5 Nonfunction G O H - +////GPIO6 unused G O L - +////GPIO7 unused G O L - +////GPIO8 BOARD ID2 G I - - +////GPIO9 unused G O L - +////GPIO10 SMC_EXTSMI# G I - I +////GPIO11 Nonfunction G O H - +////GPIO12 unused G O L - +////GPIO13 SMC_WAKE_SCI# G I - I +////GPIO14 unused G O L - +////GPIO15 unused G O L - +////GPIO16 PM_DPRSLPVR N - - - +////GNT5#/GPIO17 GNT5# N - - - +////STPPCI#/GPIO18 PM_STPPCI# N - - - +////STPCPU#/GPIO20 PM_STPCPU# N - - - +////GPIO22 CRT_RefClk G I - - +////GPIO23 unused G O L - +////GPIO24 unused G O L - +////GPIO25 DMI strap G O L - +////GPIO26 unused G O L - +////GPIO27 unused G O L - +////GPIO28 RF_KILL# G O H - +////OC5#/GPIO29 OC N - - - +////OC6#/GPIO30 OC N - - - +////OC7#/GPIO31 OC N - - - +////CLKRUN#/GPIO32 PM_CLKRUN# N - - - +////GPIO33 NC G O L - +////GPIO34 BOARD ID0 G I - - +////GPIO36 unused G O L - +////GPIO38 BOARD ID1 G I - - +////GPIO39 unused G O L - +////GPIO48 unused G O L - +////CPUPWRGD/GPIO49 H_PWRGD N - - - +// +//#define GPIO_USE_SEL_VAL 0x1FC0FFFF //GPIO1, 10, 13 is EC signal +//#define GPIO_USE_SEL2_VAL 0x000100D6 +//#define GPIO_IO_SEL_VAL 0x00402502 +//#define GPIO_IO_SEL2_VAL 0x00000044 +//#define GPIO_LVL_VAL 0x1800083D +//#define GPIO_LVL2_VAL 0x00000000 +//#define GPIO_INV_VAL 0x00002402 +//#define GPIO_BLNK_VAL 0x00000000 +//#define ICH_GPI_ROUTE (ICH_GPI_ROUTE_SCI(13) | ICH_GPI_ROUTE_SCI(1)) + +// +// GPIO Register Settings for CedarRock and CedarFalls platforms +// +// GPIO Register Settings for NB10_CRB +//--------------------------------------------------------------------------------- +//Signal Used As USE I/O LVL +//--------------------------------------------------------------------------------- +// +// GPIO0 FP_AUDIO_DETECT G I +// GPIO1 SMC_RUNTIME_SCI# G I +// GPIO2 INT_PIRQE_N N I +// GPIO3 INT_PIRQF_N N I +// GPIO4 INT_PIRQG_N N I +// GPIO5 INT_PIRQH_N N I +// GPIO6 +// GPIO7 +// GPIO8 +// GPIO9 LPC_SIO_PME G I +// GPIO10 SMC_EXTSMI_N G I +// GPIO11 SMBALERT- pullup N +// GPIO12 ICH_GP12 G I +// GPIO13 SMC_WAKE_SCI_N G I +// GPIO14 LCD_PID0 G O H +// GPIO15 CONFIG_MODE_N G I +// GPIO16 PM_DPRSLPVR N +// GPIO17 SPI_SELECT_STRAP1 +// /L_BKLTSEL0_N G I +// GPIO18 PM_STPPCI_N N +// GPIO19 +// GPIO20 PM_STPCPU_N N +// GPIO21 +// GPIO22 REQ4B G I +// GPIO23 L_DRQ1_N N +// GPIO24 CRB_SV_DET_N G O H +// GPIO25 DMI strap +// / L_BKLTSEL1_N G O H +// GPIO26 LCD_PID1 G O H +// GPIO27 TPEV_DDR3L_DETECT G O H +// GPIO28 RF_KILL G O H:enable +// GPIO29 OC N +// GPIO30 OC N +// GPIO31 OC N +// GPIO32 PM_CLKRUN_N Native +// GPIO33 MFG_MODE_N G I +// GPIO34 BOARD ID0 G I +// GPIO35 +// GPIO36 SV_SET_UP G O H +// GPIO37 +// GPIO38 BOARD ID1 G I +// GPIO39 BOARD ID2 G I +// GPIO48 FLASH_SEL0 N +// GPIO49 H_PWRGD N + +#define ICH_GPI_ROUTE_SMI(Gpio) ((( 0 << ((Gpio * 2) + 1)) | (1 << (Gpio * 2)))) +#define ICH_GPI_ROUTE_SCI(Gpio) ((( 1 << ((Gpio * 2) + 1)) | (0 << (Gpio * 2)))) + +#define GPIO_USE_SEL_VAL 0X1F42F7C3 +#define GPIO_USE_SEL2_VAL 0X000000D6 +#define GPIO_IO_SEL_VAL 0X1042B73F +#define GPIO_IO_SEL2_VAL 0X000100C6 +#define GPIO_LVL_VAL 0X1F15F601 +#define GPIO_LVL2_VAL 0X000200D7 +#define GPIO_INV_VAL 0x00002602 +#define GPIO_BLNK_VAL 0x00040000 +#define ICH_GPI_ROUTE (ICH_GPI_ROUTE_SCI(13) | ICH_GPI_ROUTE_SCI(1)) + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/HwWatchdogTimer.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/HwWatchdogTimer.h new file mode 100644 index 0000000000..61cde2f3dc --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/HwWatchdogTimer.h @@ -0,0 +1,300 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + HwWatchdogTimer.h + +Abstract: + + +--*/ + +#ifndef __EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL_H__ +#define __EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL_H__ + +#define EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL_GUID \ + { 0xd5b06d16, 0x2ea1, 0x4def, 0x98, 0xd0, 0xa0, 0x5d, 0x40, 0x72, 0x84, 0x17 } + +#define EFI_WATCHDOG_TIMER_NOT_SUPPORTED_PROTOCOL_GUID \ + { 0xe9e156ac, 0x3203, 0x4572, 0xac, 0xdf, 0x84, 0x4f, 0xdc, 0xdb, 0x6, 0xbf } + + +#include + +// +// General Purpose Constants +// +#define ICH_INSTAFLUSH_GPIO BIT16 // BIT 16 in GPIO Level 2 is GPIO 48. +#define B_INSTAFLUSH BIT4 +// +// Other Watchdog timer values +// +#define WDT_COUNTDOWN_VALUE 0x14 +#define BDS_WDT_COUNTDOWN_VALUE 0x35 + + +// +// Prototypes for the Watchdog Timer Driver Protocol +// + +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_START_TIMER) ( + VOID + ); +/*++ + + Routine Description: + This service begins the Watchdog Timer countdown. If the countdown completes prior to + Stop Timer or Restart Timer the system will reset. + + Arguments: + None + + Returns: + EFI_SUCCESS - Operation completed successfully + EFI_DEVICE_ERROR - The command was unsuccessful + +--*/ + + + +typedef +EFI_STATUS +(EFIAPI *PEI_WATCHDOG_RESET_TIMER) ( + VOID + ); +/*++ + + Routine Description: + This service resets the Watchdog Timer countdown and should only be called after the + Start Timer function. + + Arguments: + None + + Returns: + EFI_SUCCESS - Operation completed successfully + EFI_DEVICE_ERROR - The command was unsuccessful + +--*/ + + + + +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_RESTART_TIMER) ( + VOID + ); +/*++ + + Routine Description: + This service restarts the Watchdog Timer countdown and should only be called after the + Start Timer function. + + Arguments: + None + + Returns: + EFI_SUCCESS - Operation completed successfully + EFI_DEVICE_ERROR - The command was unsuccessful + +--*/ + + + + +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_STOP_TIMER) ( + VOID + ); +/*++ + + Routine Description: + This service disables the Watchdog Timer countdown. + + Arguments: + None + + Returns: + EFI_SUCCESS - Operation completed successfully + EFI_DEVICE_ERROR - The command was unsuccessful + +--*/ + + + +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_CHECK_TIMEOUT) ( + OUT HW_WATCHDOG_TIMEOUT *WatchdogTimeout + ); +/*++ + + Routine Description: + This service disables the Watchdog Timer countdown. + + Arguments: + None + + Returns: + EFI_SUCCESS - Operation completed successfully + EFI_DEVICE_ERROR - The command was unsuccessful + +--*/ + + + +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_FORCE_REBOOT) ( + IN BOOLEAN ForceTimeout, + IN UINT8 ResetType + ); +/*++ + + Routine Description: + This service forces a reboot of the system due to a reset of the POWERGOOD_PS, + POWERGOOD_CLK, and the BSEL Override + + Arguments: + None + + Returns: + This function should not return! + + EFI_DEVICE_ERROR - The command was unsuccessful and a reboot did not occur + +--*/ + + + +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_KNOWN_RESET) ( + IN BOOLEAN AllowReset + ); +/*++ + + Routine Description: + This service notifies the Watchdog Timer of the fact that a known reset is occuring. + + Arguments: + AllowReset - TRUE if a Reset is currently expected + FALSE if a Reset is not currently expected + + Returns: + This function should not return! + + EFI_DEVICE_ERROR - The command was unsuccessful and a reboot did not occur + +--*/ + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_TIMER_COUNT_DOWN_PERIOD)( + OUT UINT32 *CountdownValue + ); +/*++ + + Routine Description: + This service reads the current Watchdog Timer countdown reload value. + + Arguments: + CountdownValue - pointer to UINT32 to return the value of the reload register. + + Returns: + EFI_SUCCESS - Operation completed successfully + EFI_DEVICE_ERROR - The command was unsuccessful + +--*/ + +typedef +EFI_STATUS +(EFIAPI *EFI_SET_TIMER_COUNT_DOWN_PERIOD)( + OUT UINT32 CountdownValue + ); +/*++ + + Routine Description: + This service reads the current Watchdog Timer countdown reload value. + + Arguments: + CountdownValue - Value to set the reload register. + + Returns: + EFI_SUCCESS - Operation completed successfully + EFI_DEVICE_ERROR - The command was unsuccessful + +--*/ + +typedef +EFI_STATUS +(EFIAPI *PEI_WATCHDOG_CLEAR_TIMER_STATE) ( + ); +/*++ + + Routine Description: + This service clears the state that indicates the Watchdog Timer fired. + + Arguments: + + Returns: + EFI_SUCCESS - Operation completed successfully + EFI_DEVICE_ERROR - The command was unsuccessful + +--*/ + +typedef +EFI_STATUS +(EFIAPI *EFI_STALL_WATCHDOG_COUNTDOWN) ( + IN BOOLEAN Stall + ); +/*++ + + Routine Description: + This service disables the Watchdog Timer countdown. It also closes the recurring restart event + if the event exists. + + Arguments: + Stall - TRUE = Stop the timer countdown + FALSE = Start the timer countdown + + Returns: + EFI_SUCCESS - Operation completed successfully + EFI_DEVICE_ERROR - The command was unsuccessful + +--*/ + +typedef struct _EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL { + EFI_WATCHDOG_START_TIMER StartWatchdogTimer; + PEI_WATCHDOG_RESET_TIMER ResetWatchdogTimeout; + EFI_WATCHDOG_RESTART_TIMER RestartWatchdogTimer; + EFI_WATCHDOG_STOP_TIMER StopWatchdogTimer; + EFI_WATCHDOG_CHECK_TIMEOUT CheckWatchdogTimeout; + EFI_WATCHDOG_FORCE_REBOOT ForceReboot; + EFI_WATCHDOG_KNOWN_RESET AllowKnownReset; + EFI_GET_TIMER_COUNT_DOWN_PERIOD GetCountdownPeriod; + EFI_SET_TIMER_COUNT_DOWN_PERIOD SetCountdownPeriod; + PEI_WATCHDOG_CLEAR_TIMER_STATE ClearTimerState; + EFI_STALL_WATCHDOG_COUNTDOWN StallWatchdogCountdown; +} EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL; + +extern EFI_GUID gEfiWatchdogTimerDriverProtocolGuid; +extern EFI_GUID gEfiWatchdogTimerNotSupportedProtocolGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/I2cBus.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/I2cBus.h new file mode 100644 index 0000000000..685e563095 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/I2cBus.h @@ -0,0 +1,170 @@ +/** @file + I2C bus interface + + This layer provides I/O access to an I2C device. + + Copyright (c) 2012, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __I2C_BUS_H__ +#define __I2C_BUS_H__ + +#include + +/// +/// I2C bus protocol +/// +typedef struct _EFI_I2C_BUS_PROTOCOL EFI_I2C_BUS_PROTOCOL; + + +/** + Perform an I2C operation on the device + + This routine must be called at or below TPL_NOTIFY. For synchronous + requests this routine must be called at or below TPL_CALLBACK. + + N.B. The typical consumers of this API are the third party I2C + drivers. Extreme care must be taken by other consumers of this + API to prevent confusing the third party I2C drivers due to a + state change at the I2C device which the third party I2C drivers + did not initiate. I2C platform drivers may use this API within + these guidelines. + + This routine queues an operation to the I2C controller for execution + on the I2C bus. + + As an upper layer driver writer, the following need to be provided + to the platform vendor: + + 1. ACPI CID value or string - this is used to connect the upper layer + driver to the device. + 2. Slave address array guidance when the I2C device uses more than one + slave address. This is used to access the blocks of hardware within + the I2C device. + + @param[in] This Address of an EFI_I2C_BUS_PROTOCOL + structure + @param[in] SlaveAddressIndex Index into an array of slave addresses for + the I2C device. The values in the array are + specified by the board designer, with the + I2C device driver writer providing the slave + address order. + + For devices that have a single slave address, + this value must be zero. If the I2C device + uses more than one slave address then the third + party (upper level) I2C driver writer needs to + specify the order of entries in the slave address + array. + + \ref ThirdPartyI2cDrivers "Third Party I2C Drivers" + section in I2cMaster.h. + @param[in] Event Event to set for asynchronous operations, + NULL for synchronous operations + @param[in] RequestPacket Address of an EFI_I2C_REQUEST_PACKET + structure describing the I2C operation + @param[out] I2cStatus Optional buffer to receive the I2C operation + completion status + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_ABORTED The request did not complete because the driver + was shutdown. + @retval EFI_ACCESS_DENIED Invalid SlaveAddressIndex value + @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large. + @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation. + This could indicate the slave device is not present. + @retval EFI_INVALID_PARAMETER RequestPacket is NULL + @retval EFI_INVALID_PARAMETER TPL is too high + @retval EFI_NO_RESPONSE The I2C device is not responding to the + slave address. EFI_DEVICE_ERROR may also be + returned if the controller can not distinguish + when the NACK occurred. + @retval EFI_NOT_FOUND I2C slave address exceeds maximum address + @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for + the event and then read status pointed to by + the request packet. + @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation + @retval EFI_TIMEOUT The transaction did not complete within an internally + specified timeout period. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_BUS_START_REQUEST) ( + IN CONST EFI_I2C_BUS_PROTOCOL *This, + IN UINTN SlaveAddressIndex, + IN EFI_EVENT Event OPTIONAL, + IN CONST EFI_I2C_REQUEST_PACKET *RequestPacket, + OUT EFI_STATUS *I2cStatus OPTIONAL + ); + +/// +/// The I2C bus protocol enables access to a specific device on the I2C bus. +/// +/// Each I2C device is described as an ACPI node (HID, UID and CID) within the +/// platform layer. The I2C bus protocol enumerates the I2C devices in the +/// platform and creates a unique handle and device path for each I2C device. +/// +/// I2C slave addressing is abstracted to validate addresses and limit operation +/// to the specified I2C device. The third party providing the I2C device support +/// provides an ordered list of slave addresses for the I2C device to the team +/// building the platform layer. The platform team must preserve the order of the +/// supplied list. SlaveAddressCount is the number of entries in this list or +/// array within the platform layer. The third party device support references +/// a slave address using an index into the list or array in the range of zero +/// to SlaveAddressCount - 1. +/// +struct _EFI_I2C_BUS_PROTOCOL { + /// + /// Start an I2C operation on the bus + /// + EFI_I2C_BUS_START_REQUEST StartRequest; + + /// + /// The maximum number of slave addresses for the I2C device. The caller may + /// validate this value as a check on the platform layer's configuration. Slave + /// address selection uses an index value in the range of zero to SlaveAddressCount - 1. + /// + UINTN SlaveAddressCount; + + /// + /// Hardware revision - Matches the ACPI _HRV value + /// + /// The HardwareRevision value allows a single driver to support multiple hardware + /// revisions and implement the necessary workarounds for limitations within the + /// hardware. + /// + UINT32 HardwareRevision; + + /// + /// The maximum number of bytes the I2C host controller + /// is able to receive from the I2C bus. + /// + UINT32 MaximumReceiveBytes; + + /// + /// The maximum number of bytes the I2C host controller + /// is able to send on the I2C bus. + /// + UINT32 MaximumTransmitBytes; + + /// + /// The maximum number of bytes in the I2C bus transaction. + /// + UINT32 MaximumTotalBytes; +}; + +/// +/// GUID for the I2C bus protocol +/// +extern EFI_GUID gEfiI2cBusProtocolGuid; + +#endif // __I2C_BUS_H__ diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchExtendedReset.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchExtendedReset.h new file mode 100644 index 0000000000..574fc3e19c --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchExtendedReset.h @@ -0,0 +1,90 @@ +/*++ + +Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PchExtendedReset.h + +Abstract: + + PCH Extended Reset Protocol + +--*/ +#ifndef _EFI_PCH_EXTENDED_RESET_H_ +#define _EFI_PCH_EXTENDED_RESET_H_ + + + +// +#define EFI_PCH_EXTENDED_RESET_PROTOCOL_GUID \ + { \ + 0xf0bbfca0, 0x684e, 0x48b3, 0xba, 0xe2, 0x6c, 0x84, 0xb8, 0x9e, 0x53, 0x39 \ + } +extern EFI_GUID gEfiPchExtendedResetProtocolGuid; + +// +// Forward reference for ANSI C compatibility +// +typedef struct _EFI_PCH_EXTENDED_RESET_PROTOCOL EFI_PCH_EXTENDED_RESET_PROTOCOL; + +// +// Related Definitions +// +// +// PCH Extended Reset Types +// +typedef struct { + UINT8 PowerCycle : 1; // 0: Disabled*; 1: Enabled + UINT8 GlobalReset : 1; // 0: Disabled*; 1: Enabled + UINT8 SusPwrDnAck : 1; // 0: Do Nothing; + // 1: GPIO[30](SUS_PWR_DN_ACK) level is set low prior to Global Reset(for systems with an embedded controller) + UINT8 RsvdBits : 5; // Reserved fields for future expansion w/o protocol change +} PCH_EXTENDED_RESET_TYPES; + +// +// Member functions +// +typedef +EFI_STATUS +(EFIAPI *EFI_PCH_EXTENDED_RESET) ( + IN EFI_PCH_EXTENDED_RESET_PROTOCOL * This, + IN PCH_EXTENDED_RESET_TYPES PchExtendedResetTypes + ); + +/*++ + +Routine Description: + + Execute Pch Extended Reset from the host controller. + +Arguments: + + This - Pointer to the EFI_PCH_EXTENDED_RESET_PROTOCOL instance. + PchExtendedResetTypes - Pch Extended Reset Types which includes PowerCycle, Globalreset. + +Returns: + + Does not return if the reset takes place. + EFI_INVALID_PARAMETER - If ResetType is invalid. + +--*/ + +// +// Interface structure for the Pch Extended Reset Protocol +// +struct _EFI_PCH_EXTENDED_RESET_PROTOCOL { + EFI_PCH_EXTENDED_RESET Reset; +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchInfo.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchInfo.h new file mode 100644 index 0000000000..2a3e2b26da --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchInfo.h @@ -0,0 +1,66 @@ +/** +**/ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchInfo.h + + @brief + This file defines the PCH Info Protocol. + +**/ +#ifndef _PCH_INFO_H_ +#define _PCH_INFO_H_ + + +#define EFI_PCH_INFO_PROTOCOL_GUID \ + { \ + 0xd31f0400, 0x7d16, 0x4316, 0xbf, 0x88, 0x60, 0x65, 0x88, 0x3b, 0x40, 0x2b \ + } +extern EFI_GUID gEfiPchInfoProtocolGuid; + +/// +/// Forward reference for ANSI C compatibility +/// +typedef struct _EFI_PCH_INFO_PROTOCOL EFI_PCH_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 +/// +#define PCH_INFO_PROTOCOL_REVISION_1 1 +#define PCH_INFO_PROTOCOL_REVISION_2 2 + +/// +/// RCVersion[7:0] is the release number. +/// For example: +/// VlvFramework 0.6.0-01 should be 00 06 00 01 (0x00060001) +/// VlvFramework 0.6.2 should be 00 06 02 00 (0x00060200) +/// +#define PCH_RC_VERSION 0x01000000 + +/// +/// Protocol definition +/// +struct _EFI_PCH_INFO_PROTOCOL { + UINT8 Revision; + UINT8 BusNumber; + UINT32 RCVersion; +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchPlatformPolicy.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchPlatformPolicy.h new file mode 100644 index 0000000000..0205c01b82 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchPlatformPolicy.h @@ -0,0 +1,556 @@ +/** +**/ +/** + +Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchPlatformPolicy.h + + @brief + PCH policy protocol produced by a platform driver specifying various + expected PCH settings. This protocol is consumed by the PCH drivers. + +**/ +#ifndef _PCH_PLATFORM_POLICY_H_ +#define _PCH_PLATFORM_POLICY_H_ + + +// +#include "PchRegs.h" +#ifndef ECP_FLAG +#include "Uefi.h" +#endif + +#define DXE_PCH_PLATFORM_POLICY_PROTOCOL_GUID \ + { \ + 0x4b0165a9, 0x61d6, 0x4e23, 0xa0, 0xb5, 0x3e, 0xc7, 0x9c, 0x2e, 0x30, 0xd5 \ + } +extern EFI_GUID gDxePchPlatformPolicyProtocolGuid; + +/// +/// Forward reference for ANSI C compatibility +/// +typedef struct _DXE_PCH_PLATFORM_POLICY_PROTOCOL DXE_PCH_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_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_1 1 +#define DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_2 2 +#define DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_3 3 +#define DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_4 4 +#define DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_5 5 +#define DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_6 6 +#define DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_7 7 +#define DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_8 8 +#define DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_9 9 +#define DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_10 10 +#define DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_11 11 +#define DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_12 12 + +/// +/// Generic definitions for device enabling/disabling used by PCH code. +/// +#define PCH_DEVICE_ENABLE 1 +#define PCH_DEVICE_DISABLE 0 + +/// +/// ---------------------------- Device Enabling ------------------------------ +/// +/// PCH Device enablings +/// +typedef struct { + UINT8 Lan : 1; /// 0: Disable; 1: Enable + UINT8 Azalia : 2; /// 0: Disable; 1: Enable; 2: Auto + UINT8 Sata : 1; /// 0: Disable; 1: Enable + UINT8 Smbus : 1; /// 0: Disable; 1: Enable + UINT8 LpeEnabled : 2; /// 0: Disabled; 1: PCI Mode 2: ACPI Mode + UINT8 Reserved[1]; /// Reserved fields for future expansion w/o protocol change +} PCH_DEVICE_ENABLING; + +/// +/// ---------------------------- USB Config ----------------------------- +/// +/// +/// Overcurrent pins +/// +typedef enum { + PchUsbOverCurrentPin0 = 0, + PchUsbOverCurrentPin1, + PchUsbOverCurrentPin2, + PchUsbOverCurrentPin3, + PchUsbOverCurrentPin4, + PchUsbOverCurrentPin5, + PchUsbOverCurrentPin6, + PchUsbOverCurrentPin7, + PchUsbOverCurrentPinSkip, + PchUsbOverCurrentPinMax +} PCH_USB_OVERCURRENT_PIN; + +typedef struct { + UINT8 Enable : 1; /// 0: Disable; 1: Enable. This would take effect while UsbPerPortCtl is enabled + UINT8 Panel : 1; /// 0: Back Panel Port; 1: Front Panel Port. + UINT8 Dock : 1; /// 0: Not docking port; 1: Docking Port. + UINT8 Rsvdbits : 5; +} PCH_USB_PORT_SETTINGS; + +typedef struct { + UINT8 Enable : 1; /// 0: Disable; 1: Enable + UINT8 Rsvdbits : 7; +} PCH_USB20_CONTROLLER_SETTINGS; + +typedef struct { + UINT8 Enable : 2; /// 0: 0: Disabled; 1: PCI Mode 2: ACPI Mode + UINT8 Rsvdbits : 6; +} PCH_USBOTG_CONTROLLER_SETTINGS; + +#define PCH_XHCI_MODE_OFF 0 +#define PCH_XHCI_MODE_ON 1 +#define PCH_XHCI_MODE_AUTO 2 +#define PCH_XHCI_MODE_SMARTAUTO 3 + +#define PCH_EHCI_DEBUG_OFF 0 +#define PCH_EHCI_DEBUG_ON 1 + +#define PCH_USB_FRONT_PANEL 1 +#define PCH_USB_BACK_PANEL 0 + +typedef struct { + UINT8 Mode : 2; /// 0: Disable; 1: Enable, 2: Auto, 3: Smart Auto + UINT8 PreBootSupport : 1; /// 0: No xHCI driver available; 1: xHCI driver available + UINT8 XhciStreams : 1; /// 0: Disable; 1: Enable + UINT8 Rsvdbits : 4; +} PCH_USB30_CONTROLLER_SETTINGS; + +typedef struct { + UINT8 UsbPerPortCtl : 1; /// 0: Disable; 1: Enable Per-port enable control + UINT8 Ehci1Usbr : 1; /// 0: Disable; 1: Enable EHCI 1 USBR + UINT8 RsvdBits : 6; + PCH_USB_PORT_SETTINGS PortSettings[PCH_USB_MAX_PHYSICAL_PORTS]; + PCH_USB20_CONTROLLER_SETTINGS Usb20Settings[PchEhciControllerMax]; + PCH_USB30_CONTROLLER_SETTINGS Usb30Settings; + PCH_USBOTG_CONTROLLER_SETTINGS UsbOtgSettings; + PCH_USB_OVERCURRENT_PIN Usb20OverCurrentPins[PCH_USB_MAX_PHYSICAL_PORTS]; + PCH_USB_OVERCURRENT_PIN Usb30OverCurrentPins[PCH_XHCI_MAX_USB3_PORTS]; + /// + /// The length of Usb Port to configure the USB transmitter, + /// Bits [16:4] represents length of Usb Port in inches using octal format and [3:0] is for the decimal Point. + /// + UINT16 Usb20PortLength[PCH_EHCI_MAX_PORTS]; + UINT16 EhciDebug; + UINT16 UsbXhciLpmSupport; + +} PCH_USB_CONFIG; + +/// +/// ---------------------------- 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 { + PchPcieAspmDisabled, + PchPcieAspmL0s, + PchPcieAspmL1, + PchPcieAspmL0sL1, + PchPcieAspmAutoConfig, + PchPcieAspmMax +} PCH_PCI_EXPRESS_ASPM_CONTROL; + +/// +/// Refer to PCH EDS for the PCH implementation values corresponding +/// to below PCI-E spec defined ranges +/// +typedef enum { + PchPciECompletionTO_Default, + PchPciECompletionTO_50_100us, + PchPciECompletionTO_1_10ms, + PchPciECompletionTO_16_55ms, + PchPciECompletionTO_65_210ms, + PchPciECompletionTO_260_900ms, + PchPciECompletionTO_1_3P5s, + PchPciECompletionTO_4_13s, + PchPciECompletionTO_17_64s, + PchPciECompletionTO_Disabled +} PCH_PCIE_COMPLETION_TIMEOUT; + +typedef struct { + UINT8 Enable : 1; /// Root Port enabling, 0: Disable; 1: Enable. + UINT8 Hide : 1; /// Whether or not to hide the configuration space of this port + UINT8 SlotImplemented : 1; + UINT8 HotPlug : 1; + UINT8 PmSci : 1; + UINT8 ExtSync : 1; /// Extended Synch + UINT8 Rsvdbits : 2; + /// + /// Error handlings + /// + UINT8 UnsupportedRequestReport : 1; + UINT8 FatalErrorReport : 1; + UINT8 NoFatalErrorReport : 1; + UINT8 CorrectableErrorReport : 1; + UINT8 PmeInterrupt : 1; + UINT8 SystemErrorOnFatalError : 1; + UINT8 SystemErrorOnNonFatalError : 1; + UINT8 SystemErrorOnCorrectableError : 1; + + UINT8 AdvancedErrorReporting : 1; + UINT8 TransmitterHalfSwing : 1; + UINT8 Reserved : 6; /// Reserved fields for future expansion w/o protocol change + + UINT8 FunctionNumber; /// The function number this root port is mapped to. + UINT8 PhysicalSlotNumber; + PCH_PCIE_COMPLETION_TIMEOUT CompletionTimeout; + PCH_PCI_EXPRESS_ASPM_CONTROL Aspm; +} PCH_PCI_EXPRESS_ROOT_PORT_CONFIG; + +typedef struct { + /** + VendorId + + The vendor Id of Pci Express card ASPM setting override, 0xFFFF means any Vendor ID + + DeviceId + + The Device Id of Pci Express card ASPM setting override, 0xFFFF means any Device ID + + RevId + + The Rev Id of Pci Express card ASPM setting override, 0xFF means all steppings + + BaseClassCode + + The Base Class Code of Pci Express card ASPM setting override, 0xFF means all base class + + SubClassCode + + The Sub Class Code of Pci Express card ASPM setting override, 0xFF means all sub class + + + EndPointAspm + + The override ASPM setting from End point + **/ + UINT16 VendorId; + UINT16 DeviceId; + UINT8 RevId; + UINT8 BaseClassCode; + UINT8 SubClassCode; + PCH_PCI_EXPRESS_ASPM_CONTROL EndPointAspm; +} PCH_PCIE_DEVICE_ASPM_OVERRIDE; + +typedef struct { + UINT16 VendorId; ///< PCI configuration space offset 0 + UINT16 DeviceId; ///< PCI configuration space offset 2 + UINT8 RevId; ///< PCI configuration space offset 8; 0xFF means all steppings + /** + SnoopLatency bit definition + Note: All Reserved bits must be set to 0 + + BIT[15] - When set to 1b, indicates that the values in bits 9:0 are valid + When clear values in bits 9:0 will be ignored + BITS[14:13] - Reserved + BITS[12:10] - Value in bits 9:0 will be multiplied with the scale in these bits + 000b - 1 ns + 001b - 32 ns + 010b - 1024 ns + 011b - 32,768 ns + 100b - 1,048,576 ns + 101b - 33,554,432 ns + 110b - Reserved + 111b - Reserved + BITS[9:0] - Snoop Latency Value. The value in these bits will be multiplied with + the scale in bits 12:10 + **/ + UINT16 SnoopLatency; + /** + NonSnoopLatency bit definition + Note: All Reserved bits must be set to 0 + + BIT[15] - When set to 1b, indicates that the values in bits 9:0 are valid + When clear values in bits 9:0 will be ignored + BITS[14:13] - Reserved + BITS[12:10] - Value in bits 9:0 will be multiplied with the scale in these bits + 000b - 1 ns + 001b - 32 ns + 010b - 1024 ns + 011b - 32,768 ns + 100b - 1,048,576 ns + 101b - 33,554,432 ns + 110b - Reserved + 111b - Reserved + BITS[9:0] - Non Snoop Latency Value. The value in these bits will be multiplied with + the scale in bits 12:10 + **/ + UINT16 NonSnoopLatency; +} PCH_PCIE_DEVICE_LTR_OVERRIDE; + +typedef struct { + /// + /// Temp Bus Number range available to be assigned to + /// each root port and its downstream devices for initialization + /// of these devices before PCI Bus enumeration + /// + UINT8 TempRootPortBusNumMin; + UINT8 TempRootPortBusNumMax; + PCH_PCI_EXPRESS_ROOT_PORT_CONFIG RootPort[PCH_PCIE_MAX_ROOT_PORTS]; + BOOLEAN RootPortClockGating; + UINT8 NumOfDevAspmOverride; /// Number of PCI Express card Aspm setting override + PCH_PCIE_DEVICE_ASPM_OVERRIDE *DevAspmOverride; /// The Pointer which is point to Pci Express card Aspm setting override + UINT8 PcieDynamicGating; /// Need PMC enable it first from PMC 0x3_12 MCU 318. +} PCH_PCI_EXPRESS_CONFIG; + + +/// +/// ---------------------------- SATA Config ----------------------------- +/// +typedef enum { + PchSataSpeedSupportGen1 = 1, + PchSataSpeedSupportGen2 +} PCH_SATA_SPEED_SUPPORT; + +typedef struct { + UINT8 Enable : 1; /// 0: Disable; 1: Enable + UINT8 HotPlug : 1; /// 0: Disable; 1: Enable + UINT8 MechSw : 1; /// 0: Disable; 1: Enable + UINT8 External : 1; /// 0: Disable; 1: Enable + UINT8 SpinUp : 1; /// 0: Disable; 1: Enable the COMRESET initialization Sequence to the device + UINT8 Rsvdbits : 3; /// Reserved fields for future expansion w/o protocol change +} PCH_SATA_PORT_SETTINGS; + +typedef struct { + PCH_SATA_PORT_SETTINGS PortSettings[PCH_AHCI_MAX_PORTS]; + UINT8 RaidAlternateId : 1; /// 0: Disable; 1: Enable + UINT8 Raid0 : 1; /// 0: Disable; 1: Enable RAID0 + UINT8 Raid1 : 1; /// 0: Disable; 1: Enable RAID1 + UINT8 Raid10 : 1; /// 0: Disable; 1: Enable RAID10 + UINT8 Raid5 : 1; /// 0: Disable; 1: Enable RAID5 + UINT8 Irrt : 1; /// 0: Disable; 1: Enable Intel Rapid Recovery Technology + UINT8 OromUiBanner : 1; /// 0: Disable; 1: Enable OROM UI and BANNER + UINT8 HddUnlock : 1; /// 0: Disable; 1: Indicates that the HDD password unlock in the OS is enabled + + UINT8 LedLocate : 1; /// 0: Disable; 1: Indicates that the LED/SGPIO hardware is attached and ping to locate feature is enabled on the OS + UINT8 IrrtOnly : 1; /// 0: Disable; 1: Allow only IRRT drives to span internal and external ports + UINT8 TestMode : 1; /// 0: Disable; 1: Allow entrance to the PCH SATA test modes + UINT8 SalpSupport : 1; /// 0: Disable; 1: Enable Aggressive Link Power Management + UINT8 LegacyMode : 1; /// 0: Native PCI mode; 1: Legacy mode, when SATA controller is operating in IDE mode + UINT8 SpeedSupport : 4; /// Indicates the maximum speed the SATA controller can support + /// 1h: 1.5 Gb/s (Gen 1); 2h: 3 Gb/s(Gen 2) + + UINT8 Rsvdbits : 7; // Reserved fields for future expansion w/o protocol change +} PCH_SATA_CONFIG; +/// +/// --------------------------- AZALIA Config ------------------------------ +/// +typedef struct { + UINT32 VendorDeviceId; + UINT16 SubSystemId; + UINT8 RevisionId; /// 0xFF applies to all steppings + UINT8 FrontPanelSupport; + UINT16 NumberOfRearJacks; + UINT16 NumberOfFrontJacks; +} PCH_AZALIA_VERB_TABLE_HEADER; + +typedef struct { + PCH_AZALIA_VERB_TABLE_HEADER VerbTableHeader; + UINT32 *VerbTableData; +} PCH_AZALIA_VERB_TABLE; + +typedef struct { + UINT8 Pme : 1; /// 0: Disable; 1: Enable + UINT8 DS : 1; /// 0: Docking is not supported; 1:Docking is supported + UINT8 DA : 1; /// 0: Docking is not attached; 1:Docking is attached + UINT8 HdmiCodec : 1; /// 0: Disable; 1: Enable + UINT8 AzaliaVCi : 1; /// 0: Disable; 1: Enable + UINT8 Rsvdbits : 3; + UINT8 AzaliaVerbTableNum; /// Number of verb tables provided by platform + PCH_AZALIA_VERB_TABLE *AzaliaVerbTable; /// Pointer to the actual verb table(s) + UINT16 ResetWaitTimer; /// The delay timer after Azalia reset, the value is number of microseconds +} PCH_AZALIA_CONFIG; + +/// +/// --------------------------- Smbus Config ------------------------------ +/// +typedef struct { + UINT8 NumRsvdSmbusAddresses; + UINT8 *RsvdSmbusAddressTable; +} PCH_SMBUS_CONFIG; + +/// +/// --------------------------- Miscellaneous PM Config ------------------------------ +/// +typedef struct { + UINT8 MeWakeSts : 1; + UINT8 MeHrstColdSts : 1; + UINT8 MeHrstWarmSts : 1; + UINT8 MeHostPowerDn : 1; + UINT8 WolOvrWkSts : 1; + UINT8 Rsvdbits : 3; +} PCH_POWER_RESET_STATUS; + +typedef struct { + UINT8 PmeB0S5Dis : 1; + UINT8 WolEnableOverride : 1; + UINT8 Rsvdbits : 6; +} PCH_WAKE_CONFIG; + +typedef enum { + PchSlpS360us, + PchSlpS31ms, + PchSlpS350ms, + PchSlpS32s +} PCH_SLP_S3_MIN_ASSERT; + +typedef enum { + PchSlpS4PchTime, /// The time defined in EDS Power Sequencing and Reset Signal Timings table + PchSlpS41s, + PchSlpS42s, + PchSlpS43s, + PchSlpS44s +} PCH_SLP_S4_MIN_ASSERT; + +typedef struct { + /// + /// Specify which Power/Reset bits need to be cleared by + /// the PCH Init Driver. + /// Usually platform drivers take care of these bits, but if + /// not, let PCH Init driver clear the bits. + /// + PCH_POWER_RESET_STATUS PowerResetStatusClear; + /// + /// Specify Wake Policy + /// + PCH_WAKE_CONFIG WakeConfig; + /// + /// SLP_XX Minimum Assertion Width Policy + /// + PCH_SLP_S3_MIN_ASSERT PchSlpS3MinAssert; + PCH_SLP_S4_MIN_ASSERT PchSlpS4MinAssert; + UINT8 SlpStrchSusUp : 1; /// Enable/Disable SLP_X Stretching After SUS Well Power Up + UINT8 SlpLanLowDc : 1; + UINT8 Rsvdbits : 6; +} PCH_MISC_PM_CONFIG; + +/// +/// --------------------------- Subsystem Vendor ID / Subsystem ID Config ----- +/// +typedef struct { + UINT16 SubSystemVendorId; + UINT16 SubSystemId; +} PCH_DEFAULT_SVID_SID; + +/// +/// --------------------------- Lock Down Config ------------------------------ +/// +typedef struct { + UINT8 GlobalSmi : 1; + UINT8 BiosInterface : 1; + UINT8 RtcLock : 1; + UINT8 BiosLock : 1; + UINT8 Rsvdbits : 4; + UINT8 PchBiosLockSwSmiNumber; +} PCH_LOCK_DOWN_CONFIG; +// +// --------------------------- Serial IRQ Config ------------------------------ +// +typedef enum { + PchQuietMode, + PchContinuousMode +} PCH_SIRQ_MODE; +/// +/// Refer to SoC EDS for the details of Start Frame Pulse Width in Continuous and Quiet mode +/// + +typedef struct { + BOOLEAN SirqEnable; /// Determines if enable Serial IRQ + PCH_SIRQ_MODE SirqMode; /// Serial IRQ Mode Select +} PCH_LPC_SIRQ_CONFIG; + +/// +/// --------------------------- Power Optimizer Config ------------------------------ +/// +typedef struct { + UINT8 NumOfDevLtrOverride; /// Number of Pci Express card listed in LTR override table + PCH_PCIE_DEVICE_LTR_OVERRIDE *DevLtrOverride; /// Pointer to Pci Express devices LTR override table +} PCH_PWR_OPT_CONFIG; + +/// +/// --------------------- Low Power Input Output Config ------------------------ +/// +typedef struct { + UINT8 LpssPciModeEnabled : 1; /// Determines if LPSS PCI Mode enabled + UINT8 Dma0Enabled : 1; /// Determines if LPSS DMA1 enabled + UINT8 Dma1Enabled : 1; /// Determines if LPSS DMA2 enabled + UINT8 I2C0Enabled : 1; /// Determines if LPSS I2C #1 enabled + UINT8 I2C1Enabled : 1; /// Determines if LPSS I2C #2 enabled + UINT8 I2C2Enabled : 1; /// Determines if LPSS I2C #3 enabled + UINT8 I2C3Enabled : 1; /// Determines if LPSS I2C #4 enabled + UINT8 I2C4Enabled : 1; /// Determines if LPSS I2C #5 enabled + UINT8 I2C5Enabled : 1; /// Determines if LPSS I2C #6 enabled + UINT8 I2C6Enabled : 1; /// Determines if LPSS I2C #7 enabled + UINT8 Pwm0Enabled : 1; /// Determines if LPSS PWM #1 enabled + UINT8 Pwm1Enabled : 1; /// Determines if LPSS PWM #2 enabled + UINT8 Hsuart0Enabled : 1; /// Determines if LPSS HSUART #1 enabled + UINT8 Hsuart1Enabled : 1; /// Determines if LPSS HSUART #2 enabled + UINT8 SpiEnabled : 1; /// Determines if LPSS SPI enabled + UINT8 Rsvdbits : 2; +} PCH_LPSS_CONFIG; + +/// +/// ----------------------------- SCC Config -------------------------------- +/// +typedef struct { + UINT8 eMMCEnabled : 1; /// Determines if SCC eMMC enabled + UINT8 SdioEnabled : 1; /// Determines if SCC SDIO enabled + UINT8 SdcardEnabled : 1; /// Determines if SCC SD Card enabled + UINT8 HsiEnabled : 1; /// Determines if SCC HSI enabled + UINT8 eMMC45Enabled : 1; /// Determines if SCC eMMC 4.5 enabled + UINT8 eMMC45DDR50Enabled : 1; /// Determines if DDR50 enabled for eMMC 4.5 + UINT8 eMMC45HS200Enabled : 1; /// Determines if HS200nabled for eMMC 4.5 + UINT8 Rsvdbits : 1; + UINT8 SdCardSDR25Enabled : 1; /// Determines if SDR25 for SD Card + UINT8 SdCardDDR50Enabled : 1; /// Determines if DDR50 for SD Card + UINT8 Rsvdbits1 : 6; + UINT8 eMMC45RetuneTimerValue; /// Determines retune timer value. +} PCH_SCC_CONFIG; + +/// +/// ------------ General PCH Platform Policy protocol definition ------------ +/// +struct _DXE_PCH_PLATFORM_POLICY_PROTOCOL { + UINT8 Revision; + UINT8 BusNumber; /// PCI Bus Number of the PCH device + PCH_DEVICE_ENABLING *DeviceEnabling; + PCH_USB_CONFIG *UsbConfig; + PCH_PCI_EXPRESS_CONFIG *PciExpressConfig; + + PCH_SATA_CONFIG *SataConfig; + PCH_AZALIA_CONFIG *AzaliaConfig; + PCH_SMBUS_CONFIG *SmbusConfig; + PCH_MISC_PM_CONFIG *MiscPmConfig; + PCH_DEFAULT_SVID_SID *DefaultSvidSid; + PCH_LOCK_DOWN_CONFIG *LockDownConfig; + PCH_LPC_SIRQ_CONFIG *SerialIrqConfig; + PCH_PWR_OPT_CONFIG *PwrOptConfig; + PCH_LPSS_CONFIG *LpssConfig; + PCH_SCC_CONFIG *SccConfig; + UINT8 IdleReserve; + UINT8 EhciPllCfgEnable; + UINT8 AcpiHWRed; //Hardware Reduced Mode +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchReset.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchReset.h new file mode 100644 index 0000000000..45e2860fce --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchReset.h @@ -0,0 +1,120 @@ +/** +**/ +/** + +Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchReset.h + + @brief + PCH Reset Protocol + +**/ +#ifndef _PCH_RESET_H_ +#define _PCH_RESET_H_ + + +// +#define PCH_RESET_PROTOCOL_GUID \ + { \ + 0xdb63592c, 0xb8cc, 0x44c8, 0x91, 0x8c, 0x51, 0xf5, 0x34, 0x59, 0x8a, 0x5a \ + } +#define PCH_RESET_CALLBACK_PROTOCOL_GUID \ + { \ + 0x3a3300ab, 0xc929, 0x487d, 0xab, 0x34, 0x15, 0x9b, 0xc1, 0x35, 0x62, 0xc0 \ + } +extern EFI_GUID gPchResetProtocolGuid; +extern EFI_GUID gPchResetCallbackProtocolGuid; + +/// +/// Forward reference for ANSI C compatibility +/// +typedef struct _PCH_RESET_PROTOCOL PCH_RESET_PROTOCOL; + +typedef struct _PCH_RESET_CALLBACK_PROTOCOL PCH_RESET_CALLBACK_PROTOCOL; + +/// +/// Related Definitions +/// +/// +/// PCH Reset Types +/// +typedef enum { + ColdReset, + WarmReset, + ShutdownReset, + PowerCycleReset, + GlobalReset, + GlobalResetWithEc +} PCH_RESET_TYPE; + +/// +/// Member functions +/// +typedef +EFI_STATUS +(EFIAPI *PCH_RESET) ( + IN PCH_RESET_PROTOCOL * This, + IN PCH_RESET_TYPE PchResetType + ) +/** + + @brief + Execute Pch Reset from the host controller. + + @param[in] This Pointer to the PCH_RESET_PROTOCOL instance. + @param[in] PchResetType Pch Reset Types which includes ColdReset, WarmReset, ShutdownReset, + PowerCycleReset, GlobalReset, GlobalResetWithEc + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER If ResetType is invalid. + +**/ +; + +typedef +EFI_STATUS +(EFIAPI *PCH_RESET_CALLBACK) ( + IN PCH_RESET_TYPE PchResetType + ) +/** + + @brief + Execute call back function for Pch Reset. + + @param[in] PchResetType Pch Reset Types which includes PowerCycle, Globalreset. + + @retval EFI_SUCCESS The callback function has been done successfully + @retval EFI_NOT_FOUND Failed to find Pch Reset Callback protocol. Or, none of + callback protocol is installed. + @retval Others Do not do any reset from PCH + +**/ +; + +/// +/// Interface structure for the Pch Reset Protocol +/// +struct _PCH_RESET_PROTOCOL { + PCH_RESET Reset; +}; + +/// +/// PCH_RESET_CALLBACK_PROTOCOL Structure Definition +/// +struct _PCH_RESET_CALLBACK_PROTOCOL { + PCH_RESET_CALLBACK ResetCallback; +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchS3Support.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchS3Support.h new file mode 100644 index 0000000000..ca263c66e7 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/PchS3Support.h @@ -0,0 +1,138 @@ +/** +**/ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + PchS3Support.h + + @brief + This file defines the PCH S3 support Protocol. + +**/ +#ifndef _PCH_S3_SUPPORT_PROTOCOL_H_ +#define _PCH_S3_SUPPORT_PROTOCOL_H_ + +#ifndef ECP_FLAG +#include +#endif + +#define EFI_PCH_S3_SUPPORT_PROTOCOL_GUID \ + { \ + 0xe287d20b, 0xd897, 0x4e1e, 0xa5, 0xd9, 0x97, 0x77, 0x63, 0x93, 0x6a, 0x4 \ + } + +#include + +/// +/// Extern the GUID for protocol users. +/// +extern EFI_GUID gEfiPchS3SupportProtocolGuid; + +/// +/// Forward reference for ANSI C compatibility +/// +typedef struct _EFI_PCH_S3_SUPPORT_PROTOCOL EFI_PCH_S3_SUPPORT_PROTOCOL; + +typedef enum { + PchS3ItemTypeSendCodecCommand, + PchS3ItemTypePollStatus, + PchS3ItemTypeInitPcieRootPortDownstream, + PchS3ItemTypePcieSetPm, + PchS3ItemTypePmTimerStall, + PchS3ItemTypeMax +} EFI_PCH_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 HdaBar; + UINT32 CodecCmdData; +} EFI_PCH_S3_PARAMETER_SEND_CODEC_COMMAND; + +typedef struct { + UINT64 MmioAddress; + EFI_BOOT_SCRIPT_WIDTH Width; + UINT64 Mask; + UINT64 Value; + UINT32 Timeout; // us +} EFI_PCH_S3_PARAMETER_POLL_STATUS; + +typedef struct { + UINT8 RootPortBus; + UINT8 RootPortDevice; + UINT8 RootPortFunc; + UINT8 TempBusNumberMin; + UINT8 TempBusNumberMax; +} EFI_PCH_S3_PARAMETER_INIT_PCIE_ROOT_PORT_DOWNSTREAM; + +typedef struct { + UINT8 RootPortBus; + UINT8 RootPortDevice; + UINT8 RootPortFunc; + PCH_PCI_EXPRESS_ASPM_CONTROL RootPortAspm; + UINT8 NumOfDevAspmOverride; + UINT32 DevAspmOverrideAddr; + UINT8 TempBusNumberMin; + UINT8 TempBusNumberMax; + UINT8 NumOfDevLtrOverride; + UINT32 DevLtrOverrideAddr; +} EFI_PCH_S3_PARAMETER_PCIE_SET_PM; + +typedef struct { + UINT32 DelayTime; // us +} EFI_PCH_S3_PARAMETER_PM_TIMER_STALL; + +typedef struct { + EFI_PCH_S3_DISPATCH_ITEM_TYPE Type; + VOID *Parameter; +} EFI_PCH_S3_DISPATCH_ITEM; + +/// +/// Member functions +/// +typedef +EFI_STATUS +(EFIAPI *EFI_PCH_S3_SUPPORT_SET_S3_DISPATCH_ITEM) ( + IN EFI_PCH_S3_SUPPORT_PROTOCOL * This, + IN EFI_PCH_S3_DISPATCH_ITEM * DispatchItem, + OUT EFI_PHYSICAL_ADDRESS * S3DispatchEntryPoint + ); + +/** + + @brief + Set an item to be dispatched at S3 resume time. At the same time, the entry point + of the PCH S3 support image is returned to be used in subsequent boot script save + call + + @param[in] This Pointer to the protocol instance. + @param[in] DispatchItem The item to be dispatched. + @param[in] S3DispatchEntryPoint The entry point of the PCH S3 support image. + + @retval EFI_STATUS Successfully completed. + @retval EFI_OUT_OF_RESOURCES Out of resources. + +**/ + +/// +/// Protocol definition +/// +struct _EFI_PCH_S3_SUPPORT_PROTOCOL { + EFI_PCH_S3_SUPPORT_SET_S3_DISPATCH_ITEM SetDispatchItem; +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SdHostIo.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SdHostIo.h new file mode 100644 index 0000000000..6f6dd342cd --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SdHostIo.h @@ -0,0 +1,415 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +--*/ + + +/*++ +Module Name: + + SdHostIo.h + +Abstract: + + Interface definition for EFI_SD_HOST_IO_PROTOCOL + +--*/ + +#ifndef _SD_HOST_IO_H +#define _SD_HOST_IO_H + + +// Global ID for the EFI_SD_HOST_IO_PROTOCOL +// {B63F8EC7-A9C9-4472-A4C0-4D8BF365CC51} +// +#define EFI_SD_HOST_IO_PROTOCOL_GUID \ + { 0xb63f8ec7, 0xa9c9, 0x4472, { 0xa4, 0xc0, 0x4d, 0x8b, 0xf3, 0x65, 0xcc, 0x51 } } + +typedef struct _EFI_SD_HOST_IO_PROTOCOL EFI_SD_HOST_IO_PROTOCOL; + +// +// TODO: Move to Pci22.h +// +#define PCI_SUBCLASS_SD_HOST_CONTROLLER 0x05 +#define PCI_IF_STANDARD_HOST_NO_DMA 0x00 +#define PCI_IF_STANDARD_HOST_SUPPORT_DMA 0x01 + +// +// TODO: Retire +// +#define EFI_SD_HOST_IO_PROTOCOL_REVISION_01 0x01 + +// +// TODO: Do these belong in an Industry Standard include file? +// +// 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 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_HOST_CTL2 0x3E //hphang <- New in VLV2 +#define MMIO_CAP 0x40 +#define MMIO_CAP2 0x44 //hphang <- New in VLV2 +#define MMIO_MCCAP 0x48 +#define MMIO_FORCEEVENTCMD12ERRSTAT 0x50 //hphang <- New in VLV2 +#define MMIO_FORCEEVENTERRINTSTAT 0x52 //hphang <- New in VLV2 +#define MMIO_ADMAERRSTAT 0x54 //hphang <- New in VLV2 +#define MMIO_ADMASYSADDR 0x58 //hphang <- New in VLV2 +#define MMIO_PRESETVALUE0 0x60 //hphang <- New in VLV2 +#define MMIO_PRESETVALUE1 0x64 //hphang <- New in VLV2 +#define MMIO_PRESETVALUE2 0x68 //hphang <- New in VLV2 +#define MMIO_PRESETVALUE3 0x6C //hphang <- New in VLV2 +#define MMIO_BOOTTIMEOUTCTRL 0x70 //hphang <- New in VLV2 +#define MMIO_DEBUGSEL 0x74 //hphang <- New in VLV2 +#define MMIO_SHAREDBUS 0xE0 //hphang <- New in VLV2 +#define MMIO_SPIINTSUP 0xF0 //hphang <- New in VLV2 +#define MMIO_SLTINTSTS 0xFC +#define MMIO_CTRLRVER 0xFE + +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_HW +} RESET_TYPE; + + +typedef enum { + SDMA = 0, + ADMA2, + PIO +} DMA_MOD; + +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 SDR50Support: 1; + UINT32 SDR104Support: 1; + UINT32 DDR50Support: 1; + UINT32 Reserved0: 1; + UINT32 BusWidth4: 1; // 4 bit width + UINT32 BusWidth8: 1; // 8 bit width + UINT32 Reserved1: 6; + UINT32 SDMASupport: 1; + UINT32 ADMA2Support: 1; + UINT32 DmaMode: 2; + UINT32 ReTuneTimer: 4; + UINT32 ReTuneMode: 2; + UINT32 Reserved2: 6; + UINT32 BoundarySize; +} HOST_CAPABILITY; + +/*++ + + 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 + +--*/ +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 + ); + +/*++ + + Routine Description: + 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. + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + MaxFrequency - Max frequency in HZ + + Returns: + EFI_SUCCESS + EFI_TIMEOUT +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_CLOCK_FREQUENCY) ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 MaxFrequency + ); + +/*++ + + Routine Description: + Set bus width of the host + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + BusWidth - Bus width in 1, 4, 8 bits + + Returns: + EFI_SUCCESS + 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 + ); + +/*++ + + Routine Description: + Set voltage which could supported by the host. + Support 0(Power off the host), 1.8V, 3.0V, 3.3V + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + Voltage - Units in 0.1 V + + Returns: + EFI_SUCCESS + 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 + ); + +/*++ + + Routine Description: + Set Host High Speed + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + HighSpeed - True for High Speed Mode set, false for normal mode + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_HOST_SPEED_MODE) ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 HighSpeed + ); + +/*++ + + Routine Description: + Set High Speed Mode + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + SetHostDdrMode - True for DDR Mode set, false for normal mode + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_HOST_DDR_MODE) ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 DdrMode + ); + + +/*++ + + Routine Description: + Reset the host + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + ResetAll - TRUE to reset all + + Returns: + EFI_SUCCESS + 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 + ); + +/*++ + + Routine Description: + Reset the host + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + Enable - TRUE to enable, FALSE to disable + + Returns: + EFI_SUCCESS + 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 + ); + +/*++ + + Routine Description: + Find whether these is a card inserted into the slot. If so + init the host. If not, return EFI_NOT_FOUND. + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + + Returns: + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_DETECT_CARD_AND_INIT_HOST) ( + IN EFI_SD_HOST_IO_PROTOCOL *This + ); + +/*++ + + Routine Description: + Set the Block length + + Arguments: + This - Pointer to EFI_SD_HOST_IO_PROTOCOL + BlockLength - card supportes block length + + Returns: + EFI_SUCCESS + EFI_TIMEOUT + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SET_BLOCK_LENGTH) ( + IN EFI_SD_HOST_IO_PROTOCOL *This, + IN UINT32 BlockLength + ); + +typedef EFI_STATUS +(EFIAPI *EFI_SD_HOST_IO_PROTOCOL_SETUP_DEVICE)( + IN EFI_SD_HOST_IO_PROTOCOL *This + ); + + + +// +// Interface structure for the EFI 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_SET_HOST_DDR_MODE SetHostDdrMode; + 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_SETUP_DEVICE SetupDevice; + EFI_SD_HOST_IO_PROTOCOL_SET_HOST_SPEED_MODE SetHostSpeedMode; +}; + +extern EFI_GUID gEfiSdHostIoProtocolGuid; + +#endif + diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SmbiosSlotPopulation.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SmbiosSlotPopulation.h new file mode 100644 index 0000000000..7ba9ea3d25 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SmbiosSlotPopulation.h @@ -0,0 +1,53 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + SmbiosSlotPopulation.h + +Abstract: + + EFI SMBIOS slot structure control code. + +GUID: + {EF7BF7D6-F8FF-4a76-8247-C0D0D1CC49C0} + 0xef7bf7d6, 0xf8ff, 0x4a76, 0x82, 0x47, 0xc0, 0xd0, 0xd1, 0xcc, 0x49, 0xc0 + +Revision History + +--*/ + +#ifndef _EFI_SMBIOS_SLOT_POPULATION_H_ +#define _EFI_SMBIOS_SLOT_POPULATION_H_ + +// +// Slot Population Protocol GUID +// +#define EFI_SMBIOS_SLOT_POPULATION_GUID \ + { 0xef7bf7d6, 0xf8ff, 0x4a76, 0x82, 0x47, 0xc0, 0xd0, 0xd1, 0xcc, 0x49, 0xc0 } + +typedef struct { + UINT16 SmbiosSlotId; // SMBIOS Slot ID + BOOLEAN InUse; // Does the slot have a card in it + BOOLEAN Disabled; // Should the slot information be in SMBIOS +} EFI_SMBIOS_SLOT_ENTRY; + +typedef struct { + UINT32 NumberOfEntries; + EFI_SMBIOS_SLOT_ENTRY *SlotEntries; +} EFI_SMBIOS_SLOT_POPULATION_INFO; + +extern EFI_GUID gEfiSmbiosSlotPopulationGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SmmIchnDispatchEx.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SmmIchnDispatchEx.h new file mode 100644 index 0000000000..840015653c --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SmmIchnDispatchEx.h @@ -0,0 +1,165 @@ +/** +**/ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + SmmIchnDispatchEx.h + + @brief + SmmIchnDispatch Extended Protocol + +**/ +#ifndef _EFI_SMM_ICHN_DISPATCH_EX_H_ +#define _EFI_SMM_ICHN_DISPATCH_EX_H_ + +#ifdef ECP_FLAG +#include +#else +#include +#endif + +#define EFI_SMM_ICHN_DISPATCH_EX_PROTOCOL_GUID \ + { \ + 0x3920405b, 0xc897, 0x44da, 0x88, 0xf3, 0x4c, 0x49, 0x8a, 0x6f, 0xf7, 0x36 \ + } +extern EFI_GUID gEfiSmmIchnDispatchExProtocolGuid; + +/// +/// Forward reference for ANSI C compatibility +/// +typedef struct _EFI_SMM_ICHN_DISPATCH_EX_PROTOCOL EFI_SMM_ICHN_DISPATCH_EX_PROTOCOL; + +/// +/// Related Definitions +/// +/// +/// Ichn Dispatch Extended Types +/// +typedef enum { + IchnExPciExpress = NUM_ICHN_TYPES + 1, + IchnExMonitor, + IchnExSpi, + IchnExQRT, + IchnExGpioUnlock, + IchnExTmrOverflow, + IchnExPcie0Hotplug, + IchnExPcie1Hotplug, + IchnExPcie2Hotplug, + IchnExPcie3Hotplug, + IchnExPcie0LinkActive, + IchnExPcie1LinkActive, + IchnExPcie2LinkActive, + IchnExPcie3LinkActive, + /// + /// INSERT NEW ITEMS JUST BEFORE THIS LINE + /// + IchnExTypeMAX /// the maximum number of items in this enumeration +} EFI_SMM_ICHN_EX_SMI_TYPE; + +typedef struct { + EFI_SMM_ICHN_EX_SMI_TYPE Type; +} EFI_SMM_ICHN_DISPATCH_EX_CONTEXT; + +/// +/// Member functions +/// +typedef +VOID +(EFIAPI *EFI_SMM_ICHN_DISPATCH_EX) ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_ICHN_DISPATCH_EX_CONTEXT * DispatchContext + ); + +/** + + @brief + Dispatch function for a ICH n Extended specific SMI handler. + + @param[in] DispatchHandle Handle of this dispatch function. + @param[in] DispatchContext Pointer to the dispatch function's context. + The DispatchContext fields are filled in + by the dispatching driver prior to + invoking this dispatch function. + + @retval None + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_ICHN_EX_REGISTER) ( + IN EFI_SMM_ICHN_DISPATCH_EX_PROTOCOL * This, + IN EFI_SMM_ICHN_DISPATCH_EX DispatchFunction, + IN EFI_SMM_ICHN_DISPATCH_EX_CONTEXT * DispatchContext, + OUT EFI_HANDLE * DispatchHandle + ); + +/** + + @brief + Register a child SMI source dispatch function with a parent SMM driver + + @param[in] This Protocol instance pointer. + @param[in] DispatchFunction Pointer to dispatch function to be invoked for + this SMI source + @param[in] DispatchContext 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[in] DispatchHandle Handle of dispatch function, for when interfacing + with the parent SMM driver. + + @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 DispatchContext is invalid. The ICHN input value + is not within valid range. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_ICHN_EX_UNREGISTER) ( + IN EFI_SMM_ICHN_DISPATCH_EX_PROTOCOL * This, + IN EFI_HANDLE DispatchHandle + ); + +/** + + @brief + Unregister a child SMI source dispatch function with a parent SMM driver + + @param[in] This Protocol instance pointer. + @param[in] 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 Others TBD + +**/ + +/// +/// Interface structure for the SMM Ich n specific SMI Dispatch Protocol +/// +typedef struct _EFI_SMM_ICHN_DISPATCH_EX_PROTOCOL { + EFI_SMM_ICHN_EX_REGISTER Register; + EFI_SMM_ICHN_EX_UNREGISTER UnRegister; +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SmmSmbus.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SmmSmbus.h new file mode 100644 index 0000000000..3ee6a3a7a5 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/SmmSmbus.h @@ -0,0 +1,45 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + SmmSmbus.h + +Abstract: + + SmmSmbus Protocol + +--*/ +#ifndef __EFI_SMM_SMBUS_PROTOCOL_H__ +#define __EFI_SMM_SMBUS_PROTOCOL_H__ + +// +// GUID for the SmmSmbus Protocol +// +// EDK and EDKII have different GUID formats +// + +#define EFI_SMM_SMBUS_PROTOCOL_GUID \ + { \ + 0x72e40094, 0x2ee1, 0x497a, 0x8f, 0x33, 0x4c, 0x93, 0x4a, 0x9e, 0x9c, 0xc \ + } + +// +// Resuse the DXE definition, and use another GUID. +// +typedef EFI_SMBUS_HC_PROTOCOL SMM_SMBUS_HC_PROTOCOL; + +extern EFI_GUID gEfiSmmSmbusProtocolGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/Spi.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/Spi.h new file mode 100644 index 0000000000..f73ef65870 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/Spi.h @@ -0,0 +1,266 @@ +/** +**/ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + @file + Spi.h + + @brief + This file defines the EFI SPI Protocol which implements the + Intel(R) ICH SPI Host Controller Compatibility Interface. + +**/ +#ifndef _EFI_SPI_H_ +#define _EFI_SPI_H_ + + +// +#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 \ + } +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 + +/// +/// 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 VLV + EnumSpiCycle50MHz, + EnumSpiCycleMax +} SPI_CYCLE_FREQUENCY; + +typedef enum { + EnumSpiRegionAll, + EnumSpiRegionBios, + EnumSpiRegionSeC, + EnumSpiRegionDescriptor, + EnumSpiRegionPlatformData, + EnumSpiRegionMax +} SPI_REGION_TYPE; + +/// +/// Hardware Sequencing required operations (as listed in Valleyview EDS "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; + +/// +/// SPI Command Configuration +/// 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, and provides TYPE and Code for it in +/// SpecialOpcodeEntry. +/// +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; + +// +// Protocol member functions +// +typedef +EFI_STATUS +(EFIAPI *EFI_SPI_INIT) ( + IN EFI_SPI_PROTOCOL * This, + IN SPI_INIT_TABLE * InitTable + ); + +/** + + @brief + Initializes the host controller to execute SPI commands. + + @param[in] This Pointer to the EFI_SPI_PROTOCOL instance. + @param[in] InitData Pointer to caller-allocated buffer containing the SPI + interface initialization table. + + @retval EFI_SUCCESS Opcode initialization on the SPI host controller completed. + @retval EFI_ACCESS_DENIED The SPI configuration interface is locked. + @retval EFI_OUT_OF_RESOURCES Not enough resource available to initialize the device. + @retval EFI_DEVICE_ERROR Device error, operation failed. + +**/ + +typedef +EFI_STATUS +(EFIAPI *EFI_SPI_LOCK) ( + IN EFI_SPI_PROTOCOL * This + ); +/** + + @brief + Initializes the host controller to execute SPI commands. + + @param[in] This Pointer to the EFI_SPI_PROTOCOL instance. + @param[in] InitData Pointer to caller-allocated buffer containing the SPI + interface initialization table. + + @retval EFI_SUCCESS Opcode initialization on the SPI host controller completed. + @retval EFI_ACCESS_DENIED The SPI configuration interface is locked. + @retval EFI_OUT_OF_RESOURCES Not enough resource available to initialize the device. + @retval EFI_DEVICE_ERROR Device error, operation failed. + +**/ + +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 + ); +/** + + @brief + Execute SPI commands from the host controller. + + @param[in] This Pointer to the EFI_SPI_PROTOCOL instance. + @param[in] OpcodeIndex Index of the command in the OpCode Menu. + @param[in] PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence. + @param[in] DataCycle TRUE if the SPI cycle contains data + @param[in] Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed. + @param[in] ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in. + @param[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) + @param[in] DataByteCount Number of bytes in the data portion of the SPI cycle. + @param[in] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle. + @param[in] 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). + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @exception EFI_UNSUPPORTED Command not supported. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. + +**/ + +/// +/// Protocol definition +/// +struct _EFI_SPI_PROTOCOL { + EFI_SPI_INIT Init; + EFI_SPI_LOCK Lock; + EFI_SPI_EXECUTE Execute; +}; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/TcoReset.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/TcoReset.h new file mode 100644 index 0000000000..4cb7dba1d4 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Protocol/TcoReset.h @@ -0,0 +1,94 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + TcoReset.h + +Abstract: + + Protocol to communicate with ICH TCO. + +GUID Info: + {A6A79162-E325-4c30-BCC3-59373064EFB3} + 0xa6a79162, 0xe325, 0x4c30, 0xbc, 0xc3, 0x59, 0x37, 0x30, 0x64, 0xef, 0xb3); + + +--*/ + +#ifndef _TCO_RESET_H_ +#define _TCO_RESET_H_ + + +#define EFI_TCO_RESET_PROTOCOL_GUID \ + {0xa6a79162, 0xe325, 0x4c30, 0xbc, 0xc3, 0x59, 0x37, 0x30, 0x64, 0xef, 0xb3} + +typedef struct _EFI_TCO_RESET_PROTOCOL EFI_TCO_RESET_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *EFI_TCO_RESET_PROTOCOL_ENABLE_TCO_RESET) ( + IN UINT32 *RcrbGcsSaveValue + ) +/*++ + +Routine Description: + + Enables the TCO timer to reset the system in case of a system hang. This is + used when writing the clock registers. + +Arguments: + + RcrbGcsSaveValue - This is the value of the RCRB GCS register before it is + changed by this procedure. This will be used to restore + the settings of this register in PpiDisableTcoReset. + +Returns: + + EFI_STATUS + +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *EFI_TCO_RESET_PROTOCOL_DISABLE_TCO_RESET) ( + OUT UINT32 RcrbGcsRestoreValue + ) +/*++ + +Routine Description: + + Disables the TCO timer. This is used after writing the clock registers. + +Arguments: + + RcrbGcsRestoreValue - Value saved in PpiEnableTcoReset so that it can + restored. + +Returns: + + EFI_STATUS + +--*/ +; + +typedef struct _EFI_TCO_RESET_PROTOCOL { + EFI_TCO_RESET_PROTOCOL_ENABLE_TCO_RESET EnableTcoReset; + EFI_TCO_RESET_PROTOCOL_DISABLE_TCO_RESET DisableTcoReset; +} EFI_TCO_RESET_PROTOCOL; + +extern EFI_GUID gEfiTcoResetProtocolGuid; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Rsci.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Rsci.h new file mode 100644 index 0000000000..f914233660 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/Rsci.h @@ -0,0 +1,34 @@ +/*++ +Copyright (c) 1996 - 2014, Intel Corporation. + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + + +Abstract: + + + +--*/ + +#ifndef _RSCI_H +#define _RSCI_H + +typedef enum { + NOT_APPLICABLE_RESET = 0, + WARM_RESET = 1, + COLD_RESET = 2, + GLOBAL_RESET = 7, +}ANDROID_RESET_TYPE; + +#endif diff --git a/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/TianoApi.h b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/TianoApi.h new file mode 100644 index 0000000000..c73c68d907 --- /dev/null +++ b/Vlv2DeviceRefCodePkg/ValleyView2Soc/SouthCluster/Include/TianoApi.h @@ -0,0 +1,67 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + TianoApi.h + +Abstract: + + Tiano intrinsic definitions. + + +--*/ + +#ifndef _TIANO_API_H_ +#define _TIANO_API_H_ + +// +// Pointer to internal runtime function +// +#define EFI_INTERNAL_FUNCTION 0x00000002 + +// +// Pointer to internal runtime pointer +// +#define EFI_INTERNAL_POINTER 0x00000004 + +// +// Pointer to internal runtime pointer +// +#define EFI_IPF_GP_POINTER 0x00000008 + +#define EFI_TPL_DRIVER 6 + +// +// EFI Event Types +// +#define EFI_EVENT_TIMER 0x80000000 +#define EFI_EVENT_RUNTIME 0x40000000 +#define EFI_EVENT_RUNTIME_CONTEXT 0x20000000 + +#define EFI_EVENT_NOTIFY_WAIT 0x00000100 +#define EFI_EVENT_NOTIFY_SIGNAL 0x00000200 + +#define EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 +#define EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 + +#define EFI_EVENT_EFI_SIGNAL_MASK 0x000000FF +#define EFI_EVENT_EFI_SIGNAL_MAX 4 + +// +// Task priority level +// +#define EFI_TPL_APPLICATION 4 +#define EFI_TPL_CALLBACK 8 +#define EFI_TPL_NOTIFY 16 +#define EFI_TPL_HIGH_LEVEL 31 + +#endif diff --git a/Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec b/Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec new file mode 100644 index 0000000000..38b975498c --- /dev/null +++ b/Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec @@ -0,0 +1,121 @@ +## @file Vlv2DeviceRefCodePkg.dec +# +# Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = Vlv2DeviceRefCodePkg + PACKAGE_GUID = E4FA0DCA-91A3-4957-9344-C10BAA0BFE5F + PACKAGE_VERSION = 0.1 + +[Ppis] + gVlvPolicyPpiGuid = { 0x7D84B2C2, 0x22A1, 0x4372, {0xB1, 0x2C, 0xEB, 0xB2, 0x32, 0xD3, 0xA6, 0xA3}} + gVlvMmioPolicyPpiGuid = { 0xE767BF7F, 0x4DB6, 0x5B34, {0x10, 0x11, 0x4F, 0xBE, 0x4C, 0xA7, 0xAF, 0xD2}} + gPeiSmbusPolicyPpiGuid = { 0x63b6e435, 0x32bc, 0x49c6, {0x81, 0xbd, 0xb7, 0xa1, 0xa0, 0xfe, 0x1a, 0x6c}} + gSeCfTPMPpiGuid = { 0x10e26df1, 0x8775, 0x4ee1, {0xb5, 0x0a, 0x3a, 0xe8, 0x28, 0x93, 0x70, 0x3a}} + gPchUsbPolicyPpiGuid = { 0xc02b0573, 0x2b4e, 0x4a31, {0xa3, 0x1a, 0x94, 0x56, 0x7b, 0x50, 0x44, 0x2c}} + gPchInitPpiGuid = { 0x09ea894a, 0xbe0d, 0x4230, {0xa0, 0x03, 0xed, 0xc6, 0x93, 0xb4, 0x8e, 0x95}} + gPchPlatformPolicyPpiGuid = { 0x15344673, 0xD365, 0x4BE2, {0x85, 0x13, 0x14, 0x97, 0xCC, 0x07, 0x61, 0x1D}} + gPeiSpiPpiGuid = { 0xA38C6898, 0x2B5C, 0x4FF6, {0x93, 0x26, 0x2E, 0x63, 0x21, 0x2E, 0x56, 0xC2}} + gVlvPeiInitPpiGuid = { 0x09ea8911, 0xbe0d, 0x4230, {0xa0, 0x03, 0xed, 0xc6, 0x93, 0xb4, 0x8e, 0x11}} + gSeCUmaPpiGuid = { 0xcbd86677, 0x362f, 0x4c04, {0x94, 0x59, 0xa7, 0x41, 0x32, 0x6e, 0x05, 0xcf}} + gPeiSeCPlatformPolicyPpiGuid = { 0x7ae3ceb7, 0x2ee2, 0x48fa, {0xaa, 0x49, 0x35, 0x10, 0xbc, 0x83, 0xca, 0xbf}} + gPeiHeciPpiGuid = { 0xEE0EA811, 0xFBD9, 0x4777, {0xB9, 0x5A, 0xBA, 0x4F, 0x71, 0x10, 0x1F, 0x74}} + gPeiSdhcPpiGuid = { 0xf4ef9d7a, 0x98c5, 0x4c1a, {0xb4, 0xd9, 0xd8, 0xd8, 0x72, 0x65, 0xbe, 0x0c}} + gPeiBlockIoPpiGuid = { 0xbc5fa650, 0xedbb, 0x4d0d, {0xb3, 0xa3, 0xd9, 0x89, 0x07, 0xf8, 0x47, 0xdf}} + gSeCfTPMPolicyPpiGuid = { 0x4fd1ba49, 0x8f90, 0x471a, {0xa2, 0xc9, 0x17, 0x3c, 0x7a, 0x73, 0x2f, 0xd0}} + gEfiPeiReadOnlyVariable2PpiGuid = { 0x2ab86ef5, 0xecb5, 0x4134, {0xb5, 0x56, 0x38, 0x54, 0xca, 0x1f, 0xe1, 0xb4}} + gPchPeiInitPpiGuid = { 0xACB93B08, 0x5CDC, 0x4A8F, {0x93, 0xD4, 0x6, 0xE3, 0x42, 0xDF, 0x18, 0x2E}} + +[Protocols] + gEfiGlobalNvsAreaProtocolGuid = { 0x074e1e48, 0x8132, 0x47a1, {0x8c, 0x2c, 0x3f, 0x14, 0xad, 0x9a, 0x66, 0xdc}} + gPpmPlatformPolicyProtocolGuid = { 0xddabfeac, 0xef63, 0x452c, {0x8f, 0x39, 0xed, 0x7f, 0xae, 0xd8, 0x26, 0x5e}} + gEfiSpiProtocolGuid = { 0x1156efc6, 0xea32, 0x4396, {0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13}} + gMemInfoProtocolGuid = { 0x6f20f7c8, 0xe5ef, 0x4f21, {0x8d, 0x19, 0xed, 0xc5, 0xf0, 0xc4, 0x96, 0xae}} + gEfiSdHostIoProtocolGuid = { 0xb63f8ec7, 0xa9c9, 0x4472, {0xa4, 0xc0, 0x4d, 0x8b, 0xf3, 0x65, 0xcc, 0x51}} + gEfiSpiProtocolGuid = { 0x1156efc6, 0xea32, 0x4396, {0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13}} + gEfiSmmSpiProtocolGuid = { 0xD9072C35, 0xEB8F, 0x43AD, {0xA2, 0x20, 0x34, 0xD4, 0x0E, 0x2A, 0x82, 0x85}} + gEfiSmmIchnDispatchExProtocolGuid = { 0x3920405B, 0xC897, 0x44DA, {0x88, 0xF3, 0x4C, 0x49, 0x8A, 0x6F, 0xF7, 0x36}} + gEfiPchS3SupportProtocolGuid = { 0xE287D20B, 0xD897, 0x4E1E, {0xA5, 0xD9, 0x97, 0x77, 0x63, 0x93, 0x6A, 0x04}} + gPchResetProtocolGuid = { 0xDB63592C, 0xB8CC, 0x44C8, {0x91, 0x8C, 0x51, 0xF5, 0x34, 0x59, 0x8A, 0x5A}} + gPchResetCallbackProtocolGuid = { 0x3A3300AB, 0xC929, 0x487D, {0xAB, 0x34, 0x15, 0x9B, 0xC1, 0x35, 0x62, 0xC0}} + gDxePchPlatformPolicyProtocolGuid = { 0x4b0165a9, 0x61d6, 0x4e23, {0xa0, 0xb5, 0x3e, 0xc7, 0x9c, 0x2e, 0x30, 0xd5}} + gEfiPchInfoProtocolGuid = { 0xD31F0400, 0x7D16, 0x4316, {0xBF, 0x88, 0x60, 0x65, 0x88, 0x3B, 0x40, 0x2B}} + gEfiPchExtendedResetProtocolGuid = { 0xF0BBFCA0, 0x684E, 0x48B3, {0xBA, 0xE2, 0x6C, 0x84, 0xB8, 0x9E, 0x53, 0x39}} + gEfiActiveBiosProtocolGuid = { 0xEBBE2D1B, 0x1647, 0x4BDA, {0xAB, 0x9A, 0x78, 0x63, 0xE3, 0x96, 0xD4, 0x1A}} + gDxeIchPlatformPolicyProtocolGuid = { 0xf617b358, 0x12cf, 0x414a, {0xa0, 0x69, 0x60, 0x67, 0x7b, 0xda, 0x13, 0xb3}} + gEfiIchInfoProtocolGuid = { 0xd31f0400, 0x7d16, 0x4316, {0xbf, 0x88, 0x60, 0x65, 0x88, 0x3b, 0x40, 0x2b}} + gEfiSmmIoTrapDispatchProtocolGuid = { 0x58dc368d, 0x7bfa, 0x4e77, {0xab, 0xbc, 0x0e, 0x29, 0x41, 0x8d, 0xf9, 0x30}} + gEfiSmmSmbusProtocolGuid = { 0x72e40094, 0x2ee1, 0x497a, {0x8f, 0x33, 0x4c, 0x93, 0x4a, 0x9e, 0x9c, 0x0c}} + gDxeVlvPlatformPolicyGuid = { 0x5bab88ba, 0xe0e2, 0x4674, {0xb6, 0xad, 0xb8, 0x12, 0xf6, 0x88, 0x1c, 0xd6}} + gIgdOpRegionProtocolGuid = { 0xcdc5dddf, 0xe79d, 0x41ec, {0xa9, 0xb0, 0x65, 0x65, 0x49, 0x0d, 0xb9, 0xd3}} + gEfiHeciProtocolGuid = { 0xcfb33810, 0x6e87, 0x4284, {0xb2, 0x03, 0xa6, 0x6a, 0xbe, 0x07, 0xf6, 0xe8}} + gPlatformSeCHookProtocolGuid = { 0xbc52476e, 0xf67e, 0x4301, {0xb2, 0x62, 0x36, 0x9c, 0x48, 0x78, 0xaa, 0xc2}} + gEfiSeCRcInfoProtocolGuid = { 0x11fbfdfb, 0x10d2, 0x43e6, {0xb5, 0xb1, 0xb4, 0x38, 0x6e, 0xdc, 0xcb, 0x9a}} + gEfiTdtProtocolGuid = { 0x0bf70067, 0xd53b, 0x42df, {0xb7, 0x70, 0xe9, 0x2c, 0x91, 0xc6, 0x14, 0x11}} + gDxePlatformSeCPolicyGuid = { 0xf8bff014, 0x18fb, 0x4ef9, {0xb1, 0x0c, 0xae, 0x22, 0x73, 0x8d, 0xbe, 0xed}} + gLpssDummyProtocolGuid = { 0xaf4cc162, 0xd41c, 0x455a, {0xab, 0x45, 0x6d, 0xbc, 0xc1, 0xcd, 0x32, 0xf3}} + gEfiEmmcCardInfoProtocolGuid = { 0x1ebe5ab9, 0x2129, 0x49e7, {0x84, 0xd7, 0xee, 0xb9, 0xfc, 0xe5, 0xde, 0xdd}} + gEfiTdtOperationProtocolGuid = {0xfd301ba4, 0x5e62, 0x4679,{ 0xa0, 0x6f, 0xe0, 0x9a, 0xab, 0xdd, 0x2a, 0x91}} + gEfiConfigFileNameGuid = { 0x98B8D59B, 0xE8BA, 0x48EE, { 0x98, 0xDD, 0xC2, 0x95, 0x39, 0x2F, 0x1E, 0xDB }} + gEfiDFUResultGuid = { 0x14a7c46f, 0xbc02, 0x4047, { 0x9f, 0x18, 0xa5, 0xd7, 0x25, 0xd8, 0xbd, 0x19 }} + +[Guids] + gEfiCPTokenSpaceGuid = { 0x918211ce, 0xa1d2, 0x43a0, {0xa0, 0x4e, 0x75, 0xb5, 0xbf, 0x44, 0x50, 0x0E}} + gEfiSmbusArpMapGuid = { 0x707BE83E, 0x0BF6, 0x40A5, {0xBE, 0x64, 0x34, 0xC0, 0x3A, 0xA0, 0xB8, 0xE2}} + gEfiMemoryConfigDataGuid = { 0x80dbd530, 0xb74c, 0x4f11, {0x8c, 0x03, 0x41, 0x86, 0x65, 0x53, 0x28, 0x31}} + gEfiVLVTokenSpaceGuid = { 0xca452c68, 0xdf0c, 0x45c9, {0x82, 0xfb, 0xea, 0xe4, 0x2b, 0x31, 0x29, 0x46}} + gSataControllerDriverGuid = { 0xbb929da9, 0x68f7, 0x4035, {0xb2, 0x2c, 0xa3, 0xbb, 0x3f, 0x23, 0xda, 0x55}} + gDxePchPolicyUpdateProtocolGuid = { 0x1a819e49, 0xd8ee, 0x48cb, {0x9a, 0x9c, 0x0a, 0xa0, 0xd2, 0x81, 0x0a, 0x38}} + gPowerManagementAcpiTableStorageGuid = { 0x161be597, 0xe9c5, 0x49db, {0xae, 0x50, 0xc4, 0x62, 0xab, 0x54, 0xee, 0xda}} + gEfiSetupVariableGuid = { 0xec87d643, 0xeba4, 0x4bb5, {0xa1, 0xe5, 0x3f, 0x3e, 0x36, 0xb2, 0x0d, 0xa9}} + gBmpImageGuid = { 0x878AC2CC, 0x5343, 0x46F2, {0xB5, 0x63, 0x51, 0xF8, 0x9D, 0xAF, 0x56, 0xBA}} + gPchInitVariableGuid = { 0xe6c2f70a, 0xb604, 0x4877, {0x85, 0xba, 0xde, 0xec, 0x89, 0xe1, 0x17, 0xeb}} + gEfiMemoryConfigDataGuid = { 0x80dbd530, 0xb74c, 0x4f11, {0x8c, 0x03, 0x41, 0x86, 0x65, 0x53, 0x28, 0x31}} + gVlvRefCodePkgTokenSpaceGuid = { 0x85768E4A, 0x6CDC, 0x444E, {0x93, 0xDF, 0x93, 0x66, 0x85, 0xB5, 0xDF, 0xCC}} + gSeCPlatformReadyToBootGuid = { 0x03fdf171, 0x1d67, 0x4ace, {0xa9, 0x04, 0x3e, 0x36, 0xd3, 0x38, 0xfa, 0x74}} + gAmtReadyToBootGuid = { 0x40b09b5a, 0xf0ef, 0x4627, {0x93, 0xd5, 0x27, 0xf0, 0x4b, 0x75, 0x4d, 0x05}} + # + # According to UEFI 2.3.1 Errata C, 3.2 Globally Defined Variables. + # To prevent name collisions with possible future globally defined variables, + # other internal firmware data variables that are not defined in Table.10 must be saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE. + # + gEfiVlv2VariableGuid = { 0x10ba6bbe, 0xa97e, 0x41c3, {0x9a, 0x07, 0x60, 0x7a, 0xd9, 0xbd, 0x60, 0xe5}} + +[Includes.common] + . + ValleyView2Soc/NorthCluster/Include + ValleyView2Soc/SouthCluster/Include + ValleyView2Soc/CPU/Include + Include + +[PcdsFixedAtBuild] + gEfiVLVTokenSpaceGuid.PcdTCSmbaIoBaseAddress|0x1040|UINT16|0x10000207 + +[PcdsDynamic, PcdsDynamicEx] + gEfiVLVTokenSpaceGuid.PcdTCSmbaIoBaseAddress|0x1040|UINT16|0x10000207 + gEfiVLVTokenSpaceGuid.PcdEmmcManufacturerId|0|UINT8|0x10000208 + gEfiVLVTokenSpaceGuid.PcdProductSerialNumber|0|UINT32|0x10000209 + gEfiVLVTokenSpaceGuid.PcdMeasuredBootEnable|TRUE|BOOLEAN|0x1000020A + gEfiVLVTokenSpaceGuid.PcdFTPMErrorOccur|FALSE|BOOLEAN|0x1000020B + gEfiVLVTokenSpaceGuid.PcdFTPMErrorSkip|FALSE|BOOLEAN|0x1000020C + gEfiVLVTokenSpaceGuid.PcdFTPMCommand|0|UINT32|0x1000020D + gEfiVLVTokenSpaceGuid.PcdFTPMResponse|0|UINT32|0x1000020E + gEfiVLVTokenSpaceGuid.PcdFTPMNotRespond|FALSE|BOOLEAN|0x1000020F + gEfiVLVTokenSpaceGuid.PcdFTPMStatus|0|UINT32|0x10000210 + +[PcdsFeatureFlag] + gVlvRefCodePkgTokenSpaceGuid.PcdCeAtaSupport|FALSE|BOOLEAN|0x12 + gVlvRefCodePkgTokenSpaceGuid.PcdMmcSdMultiBlockSupport|TRUE|BOOLEAN|0x13 + diff --git a/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.c b/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.c new file mode 100644 index 0000000000..824f237777 --- /dev/null +++ b/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.c @@ -0,0 +1,1307 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + + This program and the accompanying materials are licensed and made available under + + the terms and conditions of the BSD License that accompanies this distribution. + + The full text of the license may be found at + + http://opensource.org/licenses/bsd-license.php. + + + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + + + +Module Name: + + AcpiPlatform.c + +Abstract: + + ACPI Platform Driver + + +--*/ + +#include +#include +#include +#include "AcpiPlatform.h" +#include "AcpiPlatformHooks.h" +#include "AcpiPlatformHooksLib.h" +#include "Platform.h" +#include +#include +#include "Osfr.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +CHAR16 EfiPlatformCpuInfoVariable[] = L"PlatformCpuInfo"; +CHAR16 gACPIOSFRModelStringVariableName[] = ACPI_OSFR_MODEL_STRING_VARIABLE_NAME; +CHAR16 gACPIOSFRRefDataBlockVariableName[] = ACPI_OSFR_REF_DATA_BLOCK_VARIABLE_NAME; +CHAR16 gACPIOSFRMfgStringVariableName[] = ACPI_OSFR_MFG_STRING_VARIABLE_NAME; + +EFI_CPU_IO_PROTOCOL *mCpuIo; +#ifndef __GNUC__ +#pragma optimize("", off) +#endif +BOOLEAN mFirstNotify; +EFI_PLATFORM_INFO_HOB *mPlatformInfo; +EFI_GUID mSystemConfigurationGuid = SYSTEM_CONFIGURATION_GUID; +SYSTEM_CONFIGURATION mSystemConfiguration; +SYSTEM_CONFIGURATION mSystemConfig; + +UINT8 mSmbusRsvdAddresses[] = PLATFORM_SMBUS_RSVD_ADDRESSES; +UINT8 mNumberSmbusAddress = sizeof( mSmbusRsvdAddresses ) / sizeof( mSmbusRsvdAddresses[0] ); + +/** + 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. + + @param[in] Protocol The protocol to find. + @param[in] Instance Return pointer to the first instance of the protocol. + @param[in] Type The type of protocol to locate. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The protocol could not be located. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. + +**/ +EFI_STATUS +LocateSupportProtocol ( + IN EFI_GUID *Protocol, + OUT VOID **Instance, + IN UINT32 Type + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + EFI_FV_FILETYPE FileType; + UINT32 FvStatus; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINTN Size; + UINTN Index; + + 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 (Index = 0; Index < NumberOfHandles; Index++) { + // + // Get the protocol on this handle. + // This should not fail because of LocateHandleBuffer. + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + 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_VOLUME_PROTOCOL *) (*Instance))->ReadFile ( + *Instance, + &gEfiAcpiTableStorageGuid, + NULL, + &Size, + &FileType, + &Attributes, + &FvStatus + ); + + // + // If we found it, then we are done. + // + if (!EFI_ERROR (Status)) { + 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 will update any runtime platform specific information. + This currently includes: + Setting OEM table values, ID, table ID, creator ID and creator revision. + Enabling the proper processor entries in the APIC tables. + + @param[in] Table The table to update. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +PlatformUpdateTables ( + IN OUT EFI_ACPI_COMMON_HEADER *Table + ) +{ + EFI_ACPI_DESCRIPTION_HEADER *TableHeader; + UINT8 *CurrPtr; + UINT8 *EndPtr; + ACPI_APIC_STRUCTURE_PTR *ApicPtr; + UINT8 CurrProcessor; + EFI_STATUS Status; + EFI_MP_SERVICES_PROTOCOL *MpService; + UINTN MaximumNumberOfCPUs; + UINTN NumberOfEnabledCPUs; + UINTN BufferSize; + ACPI_APIC_STRUCTURE_PTR *ProcessorLocalApicEntry; + UINTN BspIndex; + EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE *AsfEntry; + EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *HpetTbl; + UINT64 OemIdValue; + UINT8 Index; + EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Facp; + EFI_ACPI_OSFR_TABLE *OsfrTable; + EFI_ACPI_OSFR_OCUR_OBJECT *pOcurObject; + EFI_ACPI_OSFR_OCUR_OBJECT OcurObject = {{0xB46F133D, 0x235F, 0x4634, 0x9F, 0x03, 0xB1, 0xC0, 0x1C, 0x54, 0x78, 0x5B}, 0, 0, 0, 0, 0}; + CHAR16 *OcurMfgStringBuffer = NULL; + CHAR16 *OcurModelStringBuffer = NULL; + UINT8 *OcurRefDataBlockBuffer = NULL; + UINTN OcurMfgStringBufferSize; + UINTN OcurModelStringBufferSize; + UINTN OcurRefDataBlockBufferSize; +#if defined (IDCC2_SUPPORTED) && IDCC2_SUPPORTED + EFI_ACPI_ASPT_TABLE *pSpttTable; +#endif + UINT16 NumberOfHpets; + UINT16 HpetCapIdValue; + UINT32 HpetBlockID; + UINTN LocalApicCounter; + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; + UINT8 TempVal; + EFI_ACPI_3_0_IO_APIC_STRUCTURE *IOApicType; + EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *APICTableHeader; + + CurrPtr = NULL; + EndPtr = NULL; + ApicPtr = NULL; + LocalApicCounter = 0; + CurrProcessor = 0; + ProcessorLocalApicEntry = NULL; + + + if (Table->Signature != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) { + TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table; + // + // Update the OEMID. + // + OemIdValue = mPlatformInfo->AcpiOemId; + + *(UINT32 *)(TableHeader->OemId) = (UINT32)OemIdValue; + *(UINT16 *)(TableHeader->OemId + 4) = *(UINT16*)(((UINT8 *)&OemIdValue) + 4); + + if ((Table->Signature != EFI_ACPI_2_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) { + // + // Update the OEM Table ID. + // + TableHeader->OemTableId = mPlatformInfo->AcpiOemTableId; + } + + // + // Update the OEM Table ID. + // + TableHeader->OemRevision = EFI_ACPI_OEM_REVISION; + + // + // Update the creator ID. + // + TableHeader->CreatorId = EFI_ACPI_CREATOR_ID; + + // + // Update the creator revision. + // + TableHeader->CreatorRevision = EFI_ACPI_CREATOR_REVISION; + } + + // + // Complete this function. + // + // + // Locate the MP services protocol. + // + // + // 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)) { + return Status; + } + + // + // Determine the number of processors. + // + MpService->GetNumberOfProcessors ( + MpService, + &MaximumNumberOfCPUs, + &NumberOfEnabledCPUs + ); + + ASSERT (MaximumNumberOfCPUs <= MAX_CPU_NUM && NumberOfEnabledCPUs >= 1); + + + // + // Assign a invalid intial value for update. + // + // + // Update the processors in the APIC table. + // + switch (Table->Signature) { + case EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE_SIGNATURE: + // + // Update the table if ASF is enabled. Otherwise, return error so caller will not install. + // + if (mSystemConfig.Asf == 1) { + return EFI_UNSUPPORTED; + } + AsfEntry = (EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE *) Table; + TempVal = (mNumberSmbusAddress < ASF_ADDR_DEVICE_ARRAY_LENGTH)? mNumberSmbusAddress : ASF_ADDR_DEVICE_ARRAY_LENGTH; + for (Index = 0; Index < TempVal; Index++) { + AsfEntry->AsfAddr.FixedSmbusAddresses[Index] = mSmbusRsvdAddresses[Index]; + } + break; + + case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE: + + Status = MpService->WhoAmI ( + MpService, + &BspIndex + ); + + // + // PCAT_COMPAT Set to 1 indicate 8259 vectors should be disabled. + // + APICTableHeader = (EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)Table; + APICTableHeader->Flags |= EFI_ACPI_3_0_PCAT_COMPAT; + + CurrPtr = (UINT8 *) &((EFI_ACPI_DESCRIPTION_HEADER *) Table)[1]; + CurrPtr = CurrPtr + 8; + + // + // Size of Local APIC Address & Flag. + // + EndPtr = (UINT8 *) Table; + EndPtr = EndPtr + Table->Length; + while (CurrPtr < EndPtr) { + ApicPtr = (ACPI_APIC_STRUCTURE_PTR *) CurrPtr; + switch (ApicPtr->AcpiApicCommon.Type) { + case EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC: + // + // ESS override + // Fix for Ordering of MADT to be maintained as it is in MADT table. + // + // Update processor enabled or disabled and keep the local APIC + // order in MADT intact. + // + // Sanity check to make sure proc-id is not arbitrary. + // + DEBUG ((EFI_D_ERROR, "ApicPtr->AcpiLocalApic.AcpiProcessorId = %x, MaximumNumberOfCPUs = %x\n", \ + ApicPtr->AcpiLocalApic.AcpiProcessorId, MaximumNumberOfCPUs)); + if(ApicPtr->AcpiLocalApic.AcpiProcessorId > MaximumNumberOfCPUs) { + ApicPtr->AcpiLocalApic.AcpiProcessorId = (UINT8)MaximumNumberOfCPUs; + } + + BufferSize = 0; + ApicPtr->AcpiLocalApic.Flags = 0; + + for (CurrProcessor = 0; CurrProcessor < MaximumNumberOfCPUs; CurrProcessor++) { + Status = MpService->GetProcessorInfo ( + MpService, + CurrProcessor, + &ProcessorInfoBuffer + ); + + if (Status == EFI_SUCCESS && ProcessorInfoBuffer.ProcessorId == ApicPtr->AcpiLocalApic.ApicId) { + // + // Check to see whether or not a processor (or thread) is enabled. + // + if ((BspIndex == CurrProcessor) || ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0)) { + // + // Go on and check if Hyper Threading is enabled. If HT not enabled + // hide this thread from OS by not setting the flag to 1. This is the + // software way to disable Hyper Threading. Basically we just hide it + // from the OS. + // + ApicPtr->AcpiLocalApic.Flags = EFI_ACPI_1_0_LOCAL_APIC_ENABLED; + + + if(ProcessorInfoBuffer.Location.Thread != 0) { + ApicPtr->AcpiLocalApic.Flags = 0; + } + + AppendCpuMapTableEntry (&(ApicPtr->AcpiLocalApic)); + } + break; + } + } + + // + // If no APIC-ID match, the cpu may not be populated. + // + break; + + case EFI_ACPI_3_0_IO_APIC: + + IOApicType = (EFI_ACPI_3_0_IO_APIC_STRUCTURE *)CurrPtr; + IOApicType->IoApicId = 0x02; + // + // IO APIC entries can be patched here. + // + break; + } + + CurrPtr = CurrPtr + ApicPtr->AcpiApicCommon.Length; + } + break; + + case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE: + + Facp = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) Table; + Facp->Flags &= (UINT32)(~(3<<2)); + + break; + + case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: + // + // Patch the memory resource. + // + PatchDsdtTable ((EFI_ACPI_DESCRIPTION_HEADER *) Table); + break; + + case EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: + // + // Gv3 support + // + // TBD: Need re-design based on the ValleyTrail platform. + // + break; + + case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE: + // + // Adjust HPET Table to correct the Base Address. + // + // Enable HPET always as Hpet.asi always indicates that Hpet is enabled. + // + MmioOr8 (R_PCH_PCH_HPET + R_PCH_PCH_HPET_GCFG, B_PCH_PCH_HPET_GCFG_EN); + + + HpetTbl = (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *) Table; + HpetTbl->BaseAddressLower32Bit.Address = HPET_BASE_ADDRESS; + HpetTbl->EventTimerBlockId = *((UINT32*)(UINTN)HPET_BASE_ADDRESS); + + HpetCapIdValue = *(UINT16 *)(UINTN)(HPET_BASE_ADDRESS); + NumberOfHpets = HpetCapIdValue & B_PCH_PCH_HPET_GCID_NT; // Bits [8:12] contains the number of Hpets + HpetBlockID = EFI_ACPI_EVENT_TIMER_BLOCK_ID; + + if((NumberOfHpets) && (NumberOfHpets & B_PCH_PCH_HPET_GCID_NT)) { + HpetBlockID |= (NumberOfHpets); + } + HpetTbl->EventTimerBlockId = HpetBlockID; + + break; + + case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE: + // + // Update MCFG base and end bus number. + // + ((EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *) Table)->Segment[0].BaseAddress + = mPlatformInfo->PciData.PciExpressBase; + ((EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *) Table)->Segment[0].EndBusNumber + = (UINT8)RShiftU64 (mPlatformInfo->PciData.PciExpressSize, 20) - 1; + break; + + + case EFI_ACPI_OSFR_TABLE_SIGNATURE: + // + // Get size of OSFR variable. + // + OcurMfgStringBufferSize = 0; + Status = gRT->GetVariable ( + gACPIOSFRMfgStringVariableName, + &gACPIOSFRMfgStringVariableGuid, + NULL, + &OcurMfgStringBufferSize, + NULL + ); + if (Status != EFI_BUFFER_TOO_SMALL) { + // + // Variable must not be present on the system. + // + return EFI_UNSUPPORTED; + } + + // + // Allocate memory for variable data. + // + OcurMfgStringBuffer = AllocatePool (OcurMfgStringBufferSize); + Status = gRT->GetVariable ( + gACPIOSFRMfgStringVariableName, + &gACPIOSFRMfgStringVariableGuid, + NULL, + &OcurMfgStringBufferSize, + OcurMfgStringBuffer + ); + if (!EFI_ERROR (Status)) { + OcurModelStringBufferSize = 0; + Status = gRT->GetVariable ( + gACPIOSFRModelStringVariableName, + &gACPIOSFRModelStringVariableGuid, + NULL, + &OcurModelStringBufferSize, + NULL + ); + if (Status != EFI_BUFFER_TOO_SMALL) { + // + // Variable must not be present on the system. + // + return EFI_UNSUPPORTED; + } + + // + // Allocate memory for variable data. + // + OcurModelStringBuffer = AllocatePool (OcurModelStringBufferSize); + Status = gRT->GetVariable ( + gACPIOSFRModelStringVariableName, + &gACPIOSFRModelStringVariableGuid, + NULL, + &OcurModelStringBufferSize, + OcurModelStringBuffer + ); + if (!EFI_ERROR (Status)) { + OcurRefDataBlockBufferSize = 0; + Status = gRT->GetVariable ( + gACPIOSFRRefDataBlockVariableName, + &gACPIOSFRRefDataBlockVariableGuid, + NULL, + &OcurRefDataBlockBufferSize, + NULL + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Allocate memory for variable data. + // + OcurRefDataBlockBuffer = AllocatePool (OcurRefDataBlockBufferSize); + Status = gRT->GetVariable ( + gACPIOSFRRefDataBlockVariableName, + &gACPIOSFRRefDataBlockVariableGuid, + NULL, + &OcurRefDataBlockBufferSize, + OcurRefDataBlockBuffer + ); + } + OsfrTable = (EFI_ACPI_OSFR_TABLE *) Table; + // + // Currently only one object is defined: OCUR_OSFR_TABLE. + // + OsfrTable->ObjectCount = 1; + // + // Initialize table length to fixed portion of the ACPI OSFR table. + // + OsfrTable->Header.Length = sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION); + *(UINT32 *)((UINTN) OsfrTable + sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION)) = \ + (UINT32) (sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION) + sizeof (UINT32)); + pOcurObject = (EFI_ACPI_OSFR_OCUR_OBJECT *)((UINTN) OsfrTable + sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION) + \ + sizeof (UINT32)); + CopyMem (pOcurObject, &OcurObject, sizeof (EFI_ACPI_OSFR_OCUR_OBJECT)); + pOcurObject->ManufacturerNameStringOffset = (UINT32)((UINTN) pOcurObject - (UINTN) OsfrTable + \ + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT)); + pOcurObject->ModelNameStringOffset = (UINT32)((UINTN) pOcurObject - (UINTN) OsfrTable + \ + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize); + if (OcurRefDataBlockBufferSize > 0) { + pOcurObject->MicrosoftReferenceOffset = (UINT32)((UINTN) pOcurObject - (UINTN) OsfrTable + \ + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize + OcurModelStringBufferSize); + } + CopyMem ((UINTN *)((UINTN) pOcurObject + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT)), OcurMfgStringBuffer, \ + OcurMfgStringBufferSize); + CopyMem ((UINTN *)((UINTN) pOcurObject + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize), \ + OcurModelStringBuffer, OcurModelStringBufferSize); + if (OcurRefDataBlockBufferSize > 0) { + CopyMem ((UINTN *)((UINTN) pOcurObject + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize + \ + OcurModelStringBufferSize),OcurRefDataBlockBuffer, OcurRefDataBlockBufferSize); + } + OsfrTable->Header.Length += (UINT32)(OcurMfgStringBufferSize + OcurModelStringBufferSize + OcurRefDataBlockBufferSize); + OsfrTable->Header.Length += sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + sizeof (UINT32); + } + } + gBS->FreePool (OcurMfgStringBuffer); + gBS->FreePool (OcurModelStringBuffer); + gBS->FreePool (OcurRefDataBlockBuffer); + break; + default: + break; + } + + // + // + // Update the hardware signature in the FACS structure. + // + // + // Locate the SPCR table and update based on current settings. + // The user may change CR settings via setup or other methods. + // The SPCR table must match. + // + return EFI_SUCCESS; +} + +/** + +Routine Description: + + GC_TODO: Add function description. + +Arguments: + + Event - GC_TODO: add argument description + Context - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +**/ +STATIC +VOID +EFIAPI +OnReadyToBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_ACPI_TABLE_VERSION TableVersion; + EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport; + EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save; + SYSTEM_CONFIGURATION SetupVarBuffer; + UINTN VariableSize; + EFI_PLATFORM_CPU_INFO *PlatformCpuInfoPtr = NULL; + EFI_PLATFORM_CPU_INFO PlatformCpuInfo; + EFI_PEI_HOB_POINTERS GuidHob; + + if (mFirstNotify) { + return; + } + + mFirstNotify = TRUE; + + // + // To avoid compiler warning of "C4701: potentially uninitialized local variable 'PlatformCpuInfo' used". + // + PlatformCpuInfo.CpuVersion.FullCpuId = 0; + + // + // Get Platform CPU Info HOB. + // + PlatformCpuInfoPtr = NULL; + ZeroMem (&PlatformCpuInfo, sizeof(EFI_PLATFORM_CPU_INFO)); + VariableSize = sizeof(EFI_PLATFORM_CPU_INFO); + Status = gRT->GetVariable( + EfiPlatformCpuInfoVariable, + &gEfiVlv2VariableGuid, + NULL, + &VariableSize, + PlatformCpuInfoPtr + ); + if (EFI_ERROR(Status)) { + GuidHob.Raw = GetHobList (); + if (GuidHob.Raw != NULL) { + if ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformCpuInfoGuid, GuidHob.Raw)) != NULL) { + PlatformCpuInfoPtr = GET_GUID_HOB_DATA (GuidHob.Guid); + } + } + } + + if ((PlatformCpuInfoPtr != NULL)) { + CopyMem(&PlatformCpuInfo, PlatformCpuInfoPtr, sizeof(EFI_PLATFORM_CPU_INFO)); + } + + // + // Update the ACPI parameter blocks finally. + // + VariableSize = sizeof (SYSTEM_CONFIGURATION); + Status = gRT->GetVariable ( + L"Setup", + &mSystemConfigurationGuid, + NULL, + &VariableSize, + &SetupVarBuffer + ); + ASSERT_EFI_ERROR (Status); + + // + // Find the AcpiSupport protocol. + // + Status = LocateSupportProtocol (&gEfiAcpiSupportProtocolGuid, (VOID **) &AcpiSupport, 0); + ASSERT_EFI_ERROR (Status); + + TableVersion = EFI_ACPI_TABLE_VERSION_2_0; + + // + // Publish ACPI 1.0 or 2.0 Tables. + // + Status = AcpiSupport->PublishTables ( + AcpiSupport, + TableVersion + ); + ASSERT_EFI_ERROR (Status); + + // + // S3 script save. + // + Status = gBS->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid, NULL, (VOID **) &AcpiS3Save); + if (!EFI_ERROR (Status)) { + AcpiS3Save->S3Save (AcpiS3Save, NULL); + } + +} + +VOID +PR1FSASetting ( + IN VOID + ) +{ + // + // for FSA on PR1. + // + if (mPlatformInfo->BoardId == BOARD_ID_BL_FFRD && mPlatformInfo->BoardRev >= PR1) { + DEBUG((EFI_D_ERROR, "Set FSA status = 1 for FFRD PR1\n")); + mGlobalNvsArea.Area->FsaStatus = mSystemConfiguration.PchFSAOn; + } + if (mPlatformInfo->BoardId == BOARD_ID_BL_FFRD8) { + DEBUG((EFI_D_ERROR, "Set FSA status = 1 for FFRD8\n")); + mGlobalNvsArea.Area->FsaStatus = mSystemConfiguration.PchFSAOn; + } + +} + +/** + Entry point for Acpi platform driver. + + @param[in] ImageHandle A handle for the image that is initializing this driver. + @param[in] SystemTable A pointer to the EFI system table. + + @retval EFI_SUCCESS Driver initialized successfully. + @retval EFI_LOAD_ERROR Failed to Initialize or has been loaded. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +EFIAPI +AcpiPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_STATUS AcpiStatus; + EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport; + EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol; + INTN Instance; + EFI_ACPI_COMMON_HEADER *CurrentTable; + UINTN TableHandle; + UINT32 FvStatus; + UINT32 Size; + EFI_EVENT Event; + EFI_ACPI_TABLE_VERSION TableVersion; + UINTN VarSize; + UINTN SysCfgSize; + EFI_HANDLE Handle; + EFI_PS2_POLICY_PROTOCOL *Ps2Policy; + EFI_PEI_HOB_POINTERS GuidHob; + UINT8 PortData; + EFI_MP_SERVICES_PROTOCOL *MpService; + UINTN MaximumNumberOfCPUs; + UINTN NumberOfEnabledCPUs; + UINT32 Data32; + PCH_STEPPING pchStepping; + + mFirstNotify = FALSE; + + TableVersion = EFI_ACPI_TABLE_VERSION_2_0; + Instance = 0; + CurrentTable = NULL; + TableHandle = 0; + Data32 = 0; + + // + // Update HOB variable for PCI resource information. + // Get the HOB list. If it is not present, then ASSERT. + // + GuidHob.Raw = GetHobList (); + if (GuidHob.Raw != NULL) { + if ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformInfoGuid, GuidHob.Raw)) != NULL) { + mPlatformInfo = GET_GUID_HOB_DATA (GuidHob.Guid); + } + } + + // + // 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. + // + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + L"Setup", + &mSystemConfigurationGuid, + NULL, + &VarSize, + &mSystemConfiguration + ); + ASSERT_EFI_ERROR (Status); + + // + // Find the AcpiSupport protocol. + // + Status = LocateSupportProtocol (&gEfiAcpiSupportProtocolGuid, (VOID **) &AcpiSupport, 0); + ASSERT_EFI_ERROR (Status); + + // + // Locate the firmware volume protocol. + // + Status = LocateSupportProtocol (&gEfiFirmwareVolumeProtocolGuid, (VOID **) &FwVol, 1); + ASSERT_EFI_ERROR (Status); + + // + // Read the current system configuration variable store. + // + SysCfgSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable ( + L"Setup", + &gEfiNormalSetupGuid, + NULL, + &SysCfgSize, + &mSystemConfig + ); + + Status = EFI_SUCCESS; + Instance = 0; + + // + // TBD: Need re-design based on the ValleyTrail platform. + // + Status = gBS->LocateProtocol ( + &gEfiMpServiceProtocolGuid, + NULL, + (VOID **) &MpService + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Determine the number of processors. + // + MpService->GetNumberOfProcessors ( + MpService, + &MaximumNumberOfCPUs, + &NumberOfEnabledCPUs + ); + + // + // Allocate and initialize the NVS area for SMM and ASL communication. + // + Status = gBS->AllocatePool ( + EfiACPIMemoryNVS, + sizeof (EFI_GLOBAL_NVS_AREA), + (void **)&mGlobalNvsArea.Area + ); + ASSERT_EFI_ERROR (Status); + gBS->SetMem ( + mGlobalNvsArea.Area, + sizeof (EFI_GLOBAL_NVS_AREA), + 0 + ); + DEBUG((EFI_D_ERROR, "mGlobalNvsArea.Area is at 0x%X\n", mGlobalNvsArea.Area)); + + // + // Update global NVS area for ASL and SMM init code to use. + // + mGlobalNvsArea.Area->ApicEnable = 1; + mGlobalNvsArea.Area->EmaEnable = 0; + + mGlobalNvsArea.Area->NumberOfBatteries = 1; + mGlobalNvsArea.Area->BatteryCapacity0 = 100; + mGlobalNvsArea.Area->BatteryStatus0 = 84; + mGlobalNvsArea.Area->OnboardCom = 1; + mGlobalNvsArea.Area->IdeMode = 0; + mGlobalNvsArea.Area->PowerState = 0; + + mGlobalNvsArea.Area->LogicalProcessorCount = (UINT8)NumberOfEnabledCPUs; + + mGlobalNvsArea.Area->PassiveThermalTripPoint = mSystemConfiguration.PassiveThermalTripPoint; + mGlobalNvsArea.Area->PassiveTc1Value = mSystemConfiguration.PassiveTc1Value; + mGlobalNvsArea.Area->PassiveTc2Value = mSystemConfiguration.PassiveTc2Value; + mGlobalNvsArea.Area->PassiveTspValue = mSystemConfiguration.PassiveTspValue; + mGlobalNvsArea.Area->CriticalThermalTripPoint = mSystemConfiguration.CriticalThermalTripPoint; + + mGlobalNvsArea.Area->IgdPanelType = mSystemConfiguration.IgdFlatPanel; + mGlobalNvsArea.Area->IgdPanelScaling = mSystemConfiguration.PanelScaling; + mGlobalNvsArea.Area->IgdSciSmiMode = 0; + mGlobalNvsArea.Area->IgdTvFormat = 0; + mGlobalNvsArea.Area->IgdTvMinor = 0; + mGlobalNvsArea.Area->IgdSscConfig = 1; + mGlobalNvsArea.Area->IgdBiaConfig = mSystemConfiguration.IgdLcdIBia; + mGlobalNvsArea.Area->IgdBlcConfig = mSystemConfiguration.IgdLcdIGmchBlc; + mGlobalNvsArea.Area->IgdDvmtMemSize = mSystemConfiguration.IgdDvmt50TotalAlloc; + mGlobalNvsArea.Area->IgdPAVP = mSystemConfiguration.PavpMode; + + mGlobalNvsArea.Area->AlsEnable = mSystemConfiguration.AlsEnable; + mGlobalNvsArea.Area->BacklightControlSupport = 2; + mGlobalNvsArea.Area->BrightnessPercentage = 100; + mGlobalNvsArea.Area->IgdState = 1; + mGlobalNvsArea.Area->LidState = 1; + + mGlobalNvsArea.Area->DeviceId1 = 0x80000100 ; + mGlobalNvsArea.Area->DeviceId2 = 0x80000400 ; + mGlobalNvsArea.Area->DeviceId3 = 0x80000200 ; + mGlobalNvsArea.Area->DeviceId4 = 0x04; + mGlobalNvsArea.Area->DeviceId5 = 0x05; + mGlobalNvsArea.Area->NumberOfValidDeviceId = 4 ; + mGlobalNvsArea.Area->CurrentDeviceList = 0x0F ; + mGlobalNvsArea.Area->PreviousDeviceList = 0x0F ; + + mGlobalNvsArea.Area->UartSelection = mSystemConfiguration.UartInterface; + mGlobalNvsArea.Area->PcuUart1Enable = mSystemConfiguration.PcuUart1; + mGlobalNvsArea.Area->NativePCIESupport = 1; + + + + + + // + // Update BootMode: 0:ACPI mode; 1:PCI mode + // + mGlobalNvsArea.Area->LpssSccMode = mSystemConfiguration.LpssPciModeEnabled; + if (mSystemConfiguration.LpssMipiHsi == 0) { + mGlobalNvsArea.Area->MipiHsiAddr = 0; + mGlobalNvsArea.Area->MipiHsiLen = 0; + mGlobalNvsArea.Area->MipiHsi1Addr = 0; + mGlobalNvsArea.Area->MipiHsi1Len = 0; + } + + // + // Platform Flavor + // + mGlobalNvsArea.Area->PlatformFlavor = mPlatformInfo->PlatformFlavor; + + // + // Update the Platform id + // + mGlobalNvsArea.Area->BoardID = mPlatformInfo->BoardId; + + // + // Update the Board Revision + // + mGlobalNvsArea.Area->FabID = mPlatformInfo->BoardRev; + + // + // Update SOC Stepping + // + mGlobalNvsArea.Area->SocStepping = (UINT8)(PchStepping()); + + mGlobalNvsArea.Area->OtgMode = mSystemConfiguration.PchUsbOtg; + + pchStepping = PchStepping(); + if (mSystemConfiguration.UsbAutoMode == 1) { + // + // Auto mode is enabled. + // + if (PchA0 == pchStepping) { + // + // For A0, EHCI is enabled as default. + // + mSystemConfiguration.PchUsb20 = 1; + mSystemConfiguration.PchUsb30Mode = 0; + mSystemConfiguration.UsbXhciSupport = 0; + DEBUG ((EFI_D_INFO, "EHCI is enabled as default. SOC 0x%x\n", pchStepping)); + } else { + // + // For A1 and later, XHCI is enabled as default. + // + mSystemConfiguration.PchUsb20 = 0; + mSystemConfiguration.PchUsb30Mode = 1; + mSystemConfiguration.UsbXhciSupport = 1; + DEBUG ((EFI_D_INFO, "XHCI is enabled as default. SOC 0x%x\n", pchStepping)); + } + } + + mGlobalNvsArea.Area->XhciMode = mSystemConfiguration.PchUsb30Mode; + + mGlobalNvsArea.Area->Stepping = mPlatformInfo->IchRevision; + + // + // Override invalid Pre-Boot Driver and XhciMode combination. + // + if ((mSystemConfiguration.UsbXhciSupport == 0) && (mSystemConfiguration.PchUsb30Mode == 3)) { + mGlobalNvsArea.Area->XhciMode = 2; + } + if ((mSystemConfiguration.UsbXhciSupport == 1) && (mSystemConfiguration.PchUsb30Mode == 2)) { + mGlobalNvsArea.Area->XhciMode = 3; + } + + DEBUG ((EFI_D_ERROR, "ACPI NVS XHCI:0x%x\n", mGlobalNvsArea.Area->XhciMode)); + + mGlobalNvsArea.Area->PmicEnable = GLOBAL_NVS_DEVICE_DISABLE; + mGlobalNvsArea.Area->BatteryChargingSolution = GLOBAL_NVS_DEVICE_DISABLE; + mGlobalNvsArea.Area->ISPDevSel = mSystemConfiguration.ISPDevSel; + mGlobalNvsArea.Area->LpeEnable = mSystemConfiguration.Lpe; + + if (mSystemConfiguration.ISPEn == 0) { + mGlobalNvsArea.Area->ISPDevSel = GLOBAL_NVS_DEVICE_DISABLE; + } + + mGlobalNvsArea.Area->WittEnable = mSystemConfiguration.WittEnable; + mGlobalNvsArea.Area->UtsEnable = mSystemConfiguration.UtsEnable; + mGlobalNvsArea.Area->SarEnable = mSystemConfiguration.SAR1; + + + mGlobalNvsArea.Area->ReservedO = 1; + + SettingI2CTouchAddress(); + mGlobalNvsArea.Area->IdleReserve= mSystemConfiguration.IdleReserve; + // + // Read BMBOUND and store it in GlobalNVS to pass into ASL. + // + // BUGBUG: code was moved into silicon reference code. + // + if (mSystemConfiguration.eMMCBootMode== 1) { + // + // Auto detect mode. + // + DEBUG ((EFI_D_ERROR, "Auto detect mode------------start\n")); + + // + // Silicon Steppings. + // + switch (PchStepping()) { + case PchA0: // A0/A1 + case PchA1: + DEBUG ((EFI_D_ERROR, "SOC A0/A1: eMMC 4.41 Configuration\n")); + mSystemConfiguration.LpsseMMCEnabled = 1; + mSystemConfiguration.LpsseMMC45Enabled = 0; + break; + + case PchB0: // B0 and later. + default: + DEBUG ((EFI_D_ERROR, "SOC B0 and later: eMMC 4.5 Configuration\n")); + mSystemConfiguration.LpsseMMCEnabled = 0; + mSystemConfiguration.LpsseMMC45Enabled = 1; + break; + } + } else if (mSystemConfiguration.eMMCBootMode == 2) { + // + // eMMC 4.41 + // + DEBUG ((EFI_D_ERROR, "Force to eMMC 4.41 Configuration\n")); + mSystemConfiguration.LpsseMMCEnabled = 1; + mSystemConfiguration.LpsseMMC45Enabled = 0; + } else if (mSystemConfiguration.eMMCBootMode == 3) { + // + // eMMC 4.5 + // + DEBUG ((EFI_D_ERROR, "Force to eMMC 4.5 Configuration\n")); + mSystemConfiguration.LpsseMMCEnabled = 0; + mSystemConfiguration.LpsseMMC45Enabled = 1; + + } else { + // + // Disable eMMC controllers. + // + DEBUG ((EFI_D_ERROR, "Disable eMMC controllers\n")); + mSystemConfiguration.LpsseMMCEnabled = 0; + mSystemConfiguration.LpsseMMC45Enabled = 0; + } + + mGlobalNvsArea.Area->emmcVersion = 0; + if (mSystemConfiguration.LpsseMMCEnabled) { + DEBUG ((EFI_D_ERROR, "mGlobalNvsArea.Area->emmcVersion = 0\n")); + mGlobalNvsArea.Area->emmcVersion = 0; + } + + if (mSystemConfiguration.LpsseMMC45Enabled) { + DEBUG ((EFI_D_ERROR, "mGlobalNvsArea.Area->emmcVersion = 1\n")); + mGlobalNvsArea.Area->emmcVersion = 1; + } + + mGlobalNvsArea.Area->SdCardRemovable = mSystemConfiguration.SdCardRemovable; + + // + // Microsoft IOT + // + if ((mSystemConfiguration.LpssHsuart0FlowControlEnabled == 1) && \ + (mSystemConfiguration.LpssPwm0Enabled == 0) && \ + (mSystemConfiguration.LpssPwm1Enabled == 0)) { + mGlobalNvsArea.Area->MicrosoftIoT = GLOBAL_NVS_DEVICE_ENABLE; + DEBUG ((EFI_D_ERROR, "JP1 is set to be MSFT IOT configuration.\n")); + } else { + mGlobalNvsArea.Area->MicrosoftIoT = GLOBAL_NVS_DEVICE_DISABLE; + DEBUG ((EFI_D_ERROR, "JP1 is not set to be MSFT IOT configuration.\n")); + } + + // + // SIO related option. + // + Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, (void **)&mCpuIo); + ASSERT_EFI_ERROR (Status); + + mGlobalNvsArea.Area->WPCN381U = GLOBAL_NVS_DEVICE_DISABLE; + + mGlobalNvsArea.Area->DockedSioPresent = GLOBAL_NVS_DEVICE_DISABLE; + + if (mGlobalNvsArea.Area->DockedSioPresent != GLOBAL_NVS_DEVICE_ENABLE) { + // + // Check ID for SIO WPCN381U. + // + Status = mCpuIo->Io.Read ( + mCpuIo, + EfiCpuIoWidthUint8, + WPCN381U_CONFIG_INDEX, + 1, + &PortData + ); + ASSERT_EFI_ERROR (Status); + if (PortData != 0xFF) { + PortData = 0x20; + Status = mCpuIo->Io.Write ( + mCpuIo, + EfiCpuIoWidthUint8, + WPCN381U_CONFIG_INDEX, + 1, + &PortData + ); + ASSERT_EFI_ERROR (Status); + Status = mCpuIo->Io.Read ( + mCpuIo, + EfiCpuIoWidthUint8, + WPCN381U_CONFIG_DATA, + 1, + &PortData + ); + ASSERT_EFI_ERROR (Status); + if ((PortData == WPCN381U_CHIP_ID) || (PortData == WDCP376_CHIP_ID)) { + mGlobalNvsArea.Area->WPCN381U = GLOBAL_NVS_DEVICE_ENABLE; + mGlobalNvsArea.Area->OnboardCom = GLOBAL_NVS_DEVICE_ENABLE; + mGlobalNvsArea.Area->OnboardComCir = GLOBAL_NVS_DEVICE_DISABLE; + } + } + } + + + + // + // Get Ps2 policy to set. Will be use if present. + // + Status = gBS->LocateProtocol ( + &gEfiPs2PolicyProtocolGuid, + NULL, + (VOID **)&Ps2Policy + ); + if (!EFI_ERROR (Status)) { + Status = Ps2Policy->Ps2InitHardware (ImageHandle); + } + + mGlobalNvsArea.Area->SDIOMode = mSystemConfiguration.LpssSdioMode; + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiGlobalNvsAreaProtocolGuid, + &mGlobalNvsArea, + NULL + ); + + // + // Read tables from the storage file. + // + while (!EFI_ERROR (Status)) { + CurrentTable = NULL; + + Status = FwVol->ReadSection ( + FwVol, + &gEfiAcpiTableStorageGuid, + EFI_SECTION_RAW, + Instance, + (VOID **) &CurrentTable, + (UINTN *) &Size, + &FvStatus + ); + + if (!EFI_ERROR (Status)) { + // + // Allow platform specific code to reject the table or update it. + // + AcpiStatus = AcpiPlatformHooksIsActiveTable (CurrentTable); + + if (!EFI_ERROR (AcpiStatus)) { + // + // Perform any table specific updates. + // + AcpiStatus = PlatformUpdateTables (CurrentTable); + if (!EFI_ERROR (AcpiStatus)) { + // + // Add the table. + // + TableHandle = 0; + AcpiStatus = AcpiSupport->SetAcpiTable ( + AcpiSupport, + CurrentTable, + TRUE, + TableVersion, + &TableHandle + ); + ASSERT_EFI_ERROR (AcpiStatus); + } + } + + // + // Increment the instance. + // + Instance++; + } + } + + Status = EfiCreateEventReadyToBootEx ( + TPL_NOTIFY, + OnReadyToBoot, + NULL, + &Event + ); + + // + // Finished. + // + return EFI_SUCCESS; +} + +UINT8 +ReadCmosBank1Byte ( + IN UINT8 Index + ) +{ + UINT8 Data; + + IoWrite8(0x72, Index); + Data = IoRead8 (0x73); + return Data; +} + +VOID +WriteCmosBank1Byte ( + IN UINT8 Index, + IN UINT8 Data + ) +{ + IoWrite8 (0x72, Index); + IoWrite8 (0x73, Data); +} + + + +VOID +SettingI2CTouchAddress ( + IN VOID + ) +{ + if (mSystemConfiguration.I2CTouchAd == 0) { + // + // If setup menu select auto set I2C Touch Address base on board id. + // + if (mPlatformInfo->BoardId == BOARD_ID_BL_RVP || + mPlatformInfo->BoardId == BOARD_ID_BL_STHI || + mPlatformInfo->BoardId == BOARD_ID_BL_RVP_DDR3L ) { + // + //RVP + // + mGlobalNvsArea.Area->I2CTouchAddress = 0x4B; + } else if (mPlatformInfo->BoardId == BOARD_ID_BL_FFRD) { + // + //FFRD + // + mGlobalNvsArea.Area->I2CTouchAddress = 0x4A; + } else if (mPlatformInfo->BoardId == BOARD_ID_BB_RVP) { + mGlobalNvsArea.Area->I2CTouchAddress = 0x4C; + } else if (mPlatformInfo->BoardId == BOARD_ID_CVH) { + mGlobalNvsArea.Area->I2CTouchAddress = 0x4C; + } else if (mPlatformInfo->BoardId == BOARD_ID_BL_FFRD8) { + // + //FFRD8 uses 0x4A. + // + mGlobalNvsArea.Area->I2CTouchAddress = 0x4A; + } + } else { + mGlobalNvsArea.Area->I2CTouchAddress = mSystemConfiguration.I2CTouchAd; + } + DEBUG((EFI_D_ERROR, "GlobalNvsArea.Area->I2CTouchAddress: [%02x]\n", mGlobalNvsArea.Area->I2CTouchAddress)); +} + + diff --git a/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.h b/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.h new file mode 100644 index 0000000000..fbc927281f --- /dev/null +++ b/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.h @@ -0,0 +1,224 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// +// Global variables. +// +EFI_GLOBAL_NVS_AREA_PROTOCOL mGlobalNvsArea; + +// +// ACPI table information used to initialize tables. +#define EFI_ACPI_OEM_REVISION 0x00000003 +#define EFI_ACPI_CREATOR_ID SIGNATURE_32 ('V', 'L', 'V', '2') +#define EFI_ACPI_CREATOR_REVISION 0x0100000D + +#define WPCN381U_CONFIG_INDEX 0x2E +#define WPCN381U_CONFIG_DATA 0x2F +#define WPCN381U_CHIP_ID 0xF4 +#define WDCP376_CHIP_ID 0xF1 + +#define MOBILE_PLATFORM 1 +#define DESKTOP_PLATFORM 2 + +// +// Define macros to build data structure signatures from characters. +// +#ifndef EFI_SIGNATURE_16 +#define EFI_SIGNATURE_16(A, B) ((A) | (B << 8)) +#endif +#ifndef EFI_SIGNATURE_32 +#define EFI_SIGNATURE_32(A, B, C, D) (EFI_SIGNATURE_16 (A, B) | (EFI_SIGNATURE_16 (C, D) << 16)) +#endif +#ifndef EFI_SIGNATURE_64 +#define EFI_SIGNATURE_64(A, B, C, D, E, F, G, H) \ + (EFI_SIGNATURE_32 (A, B, C, D) | ((UINT64) (EFI_SIGNATURE_32 (E, F, G, H)) << 32)) +#endif + + +#define GV3_SSDT_OEM_TABLE_IDBASE 0x4000 + +// +// 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; + +// +// Protocol private structure definition. +// + +/** + Entry point of the ACPI platform driver. + + @param[in] ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver. + @param[in] SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table. + + @retval EFI_SUCCESS Driver initialized successfully. + @retval EFI_LOAD_ERROR Failed to Initialize or has been loaded. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +InstallAcpiPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Get Acpi Table Version. + + @param[in] ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver. + @param[in] SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table. + + @retval EFI_SUCCESS: Driver initialized successfully. + @retval EFI_LOAD_ERROR: Failed to Initialize or has been loaded. + @retval EFI_OUT_OF_RESOURCES: Could not allocate needed resources. + +--*/ +EFI_ACPI_TABLE_VERSION +GetAcpiTableVersion ( + VOID + ); + +/** + The funtion returns Oem specific information of Acpi Platform. + + @param[in] OemId OemId returned. + @param[in] OemTableId OemTableId returned. + @param[in] OemRevision OemRevision returned. + + @retval EFI_STATUS Status of function execution. + +**/ +EFI_STATUS +AcpiPlatformGetOemFields ( + OUT UINT8 *OemId, + OUT UINT64 *OemTableId, + OUT UINT32 *OemRevision + ); + +/** + The function returns Acpi table version. + + @param[in] + + @retval EFI_ACPI_TABLE_VERSION Acpi table version encoded as a UINT32. + +**/ +EFI_ACPI_TABLE_VERSION +AcpiPlatformGetAcpiSetting ( + VOID + ); + +/** + Entry point for Acpi platform driver. + + @param[in] ImageHandle A handle for the image that is initializing this driver. + @param[in] SystemTable A pointer to the EFI system table. + + @retval EFI_SUCCESS Driver initialized successfully. + @retval EFI_LOAD_ERROR Failed to Initialize or has been loaded. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +EFIAPI +AcpiPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +UINT8 +ReadCmosBank1Byte ( + IN UINT8 Index + ); + +VOID +WriteCmosBank1Byte ( + IN UINT8 Index, + IN UINT8 Data + ); + +VOID +SelectNFCDevice ( + IN VOID + ); + +VOID +SettingI2CTouchAddress ( + IN VOID + ); + +extern +EFI_STATUS +EFIAPI +IsctDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif diff --git a/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.inf b/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.inf new file mode 100644 index 0000000000..24fa913b33 --- /dev/null +++ b/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatform.inf @@ -0,0 +1,90 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# Module Name: +# +# AcpiPlatformBB.inf +# +# Abstract: +# +# + + + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiPlatform + FILE_GUID = F0F6F006-DAB4-44b2-A7A1-0F72EEDCA716 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = AcpiPlatformEntryPoint + +[sources.common] + AcpiPlatformHooks.c + AcpiPlatform.c + +[Packages] + Vlv2TbltDevicePkg/PlatformPkg.dec + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + +[LibraryClasses] + HobLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + DebugLib + HobLib + IoLib + PchPlatformLib + +[Guids] + gACPIOSFRMfgStringVariableGuid + gEfiAcpiTableStorageGuid + gACPIOSFRMfgStringVariableGuid + gEfiBoardFeaturesGuid + gEfiPlatformInfoGuid + gEfiNormalSetupGuid + gACPIOSFRRefDataBlockVariableGuid + gACPIOSFRModelStringVariableGuid + gEfiPlatformCpuInfoGuid + gEfiVlv2VariableGuid + +[Protocols] + gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEnhancedSpeedstepProtocolGuid + gEfiPlatformCpuProtocolGuid + gEfiAcpiSupportProtocolGuid + gEfiAcpiS3SaveProtocolGuid + gEfiCpuIoProtocolGuid + gEfiPs2PolicyProtocolGuid + gEfiFirmwareVolume2ProtocolGuid + gEfiMpServiceProtocolGuid + gEfiGlobalNvsAreaProtocolGuid + gEfiTcgProtocolGuid + gEfiFirmwareVolumeProtocolGuid + gIgdOpRegionProtocolGuid + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile + +[Depex] + gEfiAcpiSupportProtocolGuid AND + gEfiMpServiceProtocolGuid AND + gEfiCpuIoProtocolGuid + diff --git a/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatformHooks.c b/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatformHooks.c new file mode 100644 index 0000000000..3489650808 --- /dev/null +++ b/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatformHooks.c @@ -0,0 +1,500 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + AcpiPlatformHooks.c + +Abstract: + + ACPI Platform Driver Hooks + +--*/ + +// +// Statements that include other files. +// +#include "AcpiPlatform.h" +#include "AcpiPlatformHooks.h" +#include "Platform.h" + +// +// Prototypes of the various hook functions. +// +#include "AcpiPlatformHooksLib.h" + +extern EFI_GLOBAL_NVS_AREA_PROTOCOL mGlobalNvsArea; +extern SYSTEM_CONFIGURATION mSystemConfiguration; + +ENHANCED_SPEEDSTEP_PROTOCOL *mEistProtocol = NULL; + +EFI_CPU_ID_MAP mCpuApicIdAcpiIdMapTable[MAX_CPU_NUM]; + +EFI_STATUS +AppendCpuMapTableEntry ( + IN EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE *AcpiLocalApic + ) +{ + BOOLEAN Added; + UINTN Index; + + for (Index = 0; Index < MAX_CPU_NUM; Index++) { + if ((mCpuApicIdAcpiIdMapTable[Index].ApicId == AcpiLocalApic->ApicId) && mCpuApicIdAcpiIdMapTable[Index].Flags) { + return EFI_SUCCESS; + } + } + + Added = FALSE; + for (Index = 0; Index < MAX_CPU_NUM; Index++) { + if (!mCpuApicIdAcpiIdMapTable[Index].Flags) { + mCpuApicIdAcpiIdMapTable[Index].Flags = 1; + mCpuApicIdAcpiIdMapTable[Index].ApicId = AcpiLocalApic->ApicId; + mCpuApicIdAcpiIdMapTable[Index].AcpiProcessorId = AcpiLocalApic->AcpiProcessorId; + Added = TRUE; + break; + } + } + + ASSERT (Added); + return EFI_SUCCESS; +} + +UINT32 +ProcessorId2ApicId ( + UINT32 AcpiProcessorId + ) +{ + UINTN Index; + + ASSERT (AcpiProcessorId < MAX_CPU_NUM); + for (Index = 0; Index < MAX_CPU_NUM; Index++) { + if (mCpuApicIdAcpiIdMapTable[Index].Flags && (mCpuApicIdAcpiIdMapTable[Index].AcpiProcessorId == AcpiProcessorId)) { + return mCpuApicIdAcpiIdMapTable[Index].ApicId; + } + } + + return (UINT32) -1; +} + +UINT8 +GetProcNumberInPackage ( + IN UINT8 Package + ) +{ + UINTN Index; + UINT8 Number; + + Number = 0; + for (Index = 0; Index < MAX_CPU_NUM; Index++) { + if (mCpuApicIdAcpiIdMapTable[Index].Flags && (((mCpuApicIdAcpiIdMapTable[Index].ApicId >> 0x04) & 0x01) == Package)) { + Number++; + } + } + + return Number; +} + +EFI_STATUS +LocateCpuEistProtocol ( + IN UINT32 CpuIndex, + OUT ENHANCED_SPEEDSTEP_PROTOCOL **EistProtocol + ) +{ + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + ENHANCED_SPEEDSTEP_PROTOCOL *EistProt; + UINTN Index; + UINT32 ApicId; + EFI_STATUS Status; + + HandleCount = 0; + gBS->LocateHandleBuffer ( + ByProtocol, + &gEnhancedSpeedstepProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + Index = 0; + EistProt = NULL; + Status = EFI_NOT_FOUND; + while (Index < HandleCount) { + gBS->HandleProtocol ( + HandleBuffer[Index], + &gEnhancedSpeedstepProtocolGuid, + (VOID **) &EistProt + ); + // + // Adjust the CpuIndex by +1 due to the AcpiProcessorId is 1 based. + // + ApicId = ProcessorId2ApicId (CpuIndex+1); + if (ApicId == (UINT32) -1) { + break; + } + + if (EistProt->ProcApicId == ApicId) { + Status = EFI_SUCCESS; + break; + } + + Index++; + } + + if (HandleBuffer != NULL) { + gBS->FreePool (HandleBuffer); + } + + if (!EFI_ERROR (Status)) { + *EistProtocol = EistProt; + } else { + *EistProtocol = NULL; + } + + return Status; +} + +EFI_STATUS +PlatformHookInit ( + VOID + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + &gEnhancedSpeedstepProtocolGuid, + NULL, + (VOID **) &mEistProtocol + ); + + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Called for every ACPI table found in the BIOS flash. + Returns whether a table is active or not. Inactive tables + are not published in the ACPI table list. + + This hook can be used to implement optional SSDT tables or + enabling/disabling specific functionality (e.g. SPCR table) + based on a setup switch or platform preference. In case of + optional SSDT tables,the platform flash will include all the + SSDT tables but will return EFI_SUCCESS only for those tables + that need to be published. + + @param[in] *Table Pointer to the active table. + + @retval EFI_SUCCESS if the table is active. + @retval EFI_UNSUPPORTED if the table is not active. + +**/ +EFI_STATUS +AcpiPlatformHooksIsActiveTable ( + IN OUT EFI_ACPI_COMMON_HEADER *Table + ) +{ + EFI_ACPI_DESCRIPTION_HEADER *TableHeader; + + TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table; + + if (TableHeader->Signature == EFI_ACPI_2_0_STATIC_RESOURCE_AFFINITY_TABLE_SIGNATURE) { + + } + + if ((mSystemConfiguration.ENDBG2 == 0) && (CompareMem (&TableHeader->OemTableId, "INTLDBG2", 8) == 0)) { + return EFI_UNSUPPORTED; + } + return EFI_SUCCESS; +} + +/** + Update the GV3 SSDT table. + + @param[in][out] *TableHeader The table to be set. + + @retval EFI_SUCCESS Returns Success. + +**/ +EFI_STATUS +PatchGv3SsdtTable ( + IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader + ) +{ + EFI_STATUS Status; + UINT8 *CurrPtr; + UINT8 *SsdtPointer; + UINT32 Signature; + UINT32 CpuFixes; + UINT32 NpssFixes; + UINT32 SpssFixes; + UINT32 CpuIndex; + UINT32 PackageSize; + UINT32 NewPackageSize; + UINT32 AdjustSize; + UINTN EntryIndex; + UINTN TableIndex; + EFI_ACPI_NAME_COMMAND *PssTable; + EFI_PSS_PACKAGE *PssTableItemPtr; + ENHANCED_SPEEDSTEP_PROTOCOL *EistProt; + EIST_INFORMATION *EistInfo; + EFI_ACPI_CPU_PSS_STATE *PssState; + EFI_ACPI_NAMEPACK_DWORD *NamePtr; + // + // Loop through the ASL looking for values that we must fix up. + // + NpssFixes = 0; + SpssFixes = 0; + CpuFixes = 0; + CpuIndex = 0; + CurrPtr = (UINT8 *) TableHeader; + + EistProt = NULL; + for (SsdtPointer = CurrPtr; SsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); SsdtPointer++) { + Signature = *(UINT32 *) SsdtPointer; + switch (Signature) { + + case SIGNATURE_32 ('_', 'P', 'R', '_'): + // + // _CPUX ('0' to '0xF') + // + CpuIndex = *(SsdtPointer + 7); + if (CpuIndex >= '0' && CpuIndex <= '9') { + CpuIndex -= '0'; + } else { + if (CpuIndex > '9') { + CpuIndex -= '7'; + } + } + + CpuFixes++; + LocateCpuEistProtocol (CpuIndex, &EistProt); + break; + + case SIGNATURE_32 ('D', 'O', 'M', 'N'): + + NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer); + if (NamePtr->StartByte != AML_NAME_OP) { + continue; + } + + if (NamePtr->Size != AML_NAME_DWORD_SIZE) { + continue; + } + + NamePtr->Value = 0; + + if (mCpuApicIdAcpiIdMapTable[CpuIndex].Flags) { + NamePtr->Value = (mCpuApicIdAcpiIdMapTable[CpuIndex].ApicId >> 0x04) & 0x01; + } + break; + + case SIGNATURE_32 ('N', 'C', 'P', 'U'): + + NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer); + if (NamePtr->StartByte != AML_NAME_OP) { + continue; + } + + if (NamePtr->Size != AML_NAME_DWORD_SIZE) { + continue; + } + + NamePtr->Value = 0; + if (mCpuApicIdAcpiIdMapTable[CpuIndex].Flags) { + NamePtr->Value = GetProcNumberInPackage ((mCpuApicIdAcpiIdMapTable[CpuIndex].ApicId >> 0x04) & 0x01); + } + break; + + case SIGNATURE_32 ('N', 'P', 'S', 'S'): + case SIGNATURE_32 ('S', 'P', 'S', 'S'): + if (EistProt == NULL) { + continue; + } + + PssTable = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer); + if (PssTable->StartByte != AML_NAME_OP) { + continue; + } + + Status = EistProt->GetEistTable (EistProt, &EistInfo, (VOID **) &PssState); + + AdjustSize = PssTable->NumEntries * sizeof (EFI_PSS_PACKAGE); + AdjustSize -= EistInfo->NumStates * sizeof (EFI_PSS_PACKAGE); + PackageSize = (PssTable->Size & 0xF) + ((PssTable->Size & 0xFF00) >> 4); + NewPackageSize = PackageSize - AdjustSize; + PssTable->Size = (UINT16) ((NewPackageSize & 0xF) + ((NewPackageSize & 0x0FF0) << 4)); + + // + // Set most significant two bits of byte zero to 01, meaning two bytes used. + // + PssTable->Size |= 0x40; + + // + // Set unused table to Noop Code. + // + SetMem( (UINT8 *) PssTable + NewPackageSize + AML_NAME_PREFIX_SIZE, AdjustSize, AML_NOOP_OP); + PssTable->NumEntries = (UINT8) EistInfo->NumStates; + PssTableItemPtr = (EFI_PSS_PACKAGE *) ((UINT8 *) PssTable + sizeof (EFI_ACPI_NAME_COMMAND)); + + // + // Update the size. + // + for (TableIndex = 0; TableIndex < EistInfo->NumStates; TableIndex++) { + EntryIndex = EistInfo->NumStates - TableIndex - 1; + PssTableItemPtr->CoreFreq = PssState[EntryIndex].CoreFrequency * PssState[EntryIndex].Control; + PssTableItemPtr->Power = PssState[EntryIndex].Power * 1000; + if (PssTable->NameStr == SIGNATURE_32 ('N', 'P', 'S', 'S')) { + PssTableItemPtr->BMLatency = PssState[EntryIndex].BusMasterLatency; + PssTableItemPtr->TransLatency = PssState[EntryIndex].TransitionLatency; + } else { + // + // This method should be supported by SMM PPM Handler. + // + PssTableItemPtr->BMLatency = PssState[EntryIndex].BusMasterLatency * 2; + PssTableItemPtr->TransLatency = PssState[EntryIndex].TransitionLatency * 10; + } + + PssTableItemPtr->Control = PssState[EntryIndex].Control; + PssTableItemPtr->Status = PssState[EntryIndex].Status; + PssTableItemPtr++; + } + + if (PssTable->NameStr == SIGNATURE_32 ('N', 'P', 'S', 'S')) { + NpssFixes++; + } else { + SpssFixes++; + } + + SsdtPointer = (UINT8 *) PssTable + PackageSize; + break; + } + } + + // + // N fixes together currently. + // + ASSERT (CpuFixes == (UINT32) MAX_CPU_NUM); + ASSERT (SpssFixes == NpssFixes); + ASSERT (CpuFixes >= SpssFixes); + + return EFI_SUCCESS; +} + +/** + Update the DSDT table. + + @param[in][out] *TableHeader The table to be set. + + @retval EFI_SUCCESS Returns EFI_SUCCESS. + +**/ +EFI_STATUS +PatchDsdtTable ( + IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader + ) +{ + + UINT8 *CurrPtr; + UINT8 *DsdtPointer; + UINT32 *Signature; + UINT8 *EndPtr; + UINT8 *Operation; + UINT32 *Address; + UINT16 *Size; + + // + // Fix PCI32 resource "FIX0" -- PSYS system status area + // + CurrPtr = (UINT8*) &((EFI_ACPI_DESCRIPTION_HEADER*) TableHeader)[0]; + EndPtr = (UINT8*) TableHeader; + EndPtr = EndPtr + TableHeader->Length; + while (CurrPtr < (EndPtr-2)) { + // + // Removed the _S3 tag to indicate that we do not support S3. The 4th byte is blank space + // since there are only 3 char "_S3". + // + if (mSystemConfiguration.AcpiSuspendState == 0) { + // + // For iasl compiler version 20061109. + // + if ((CurrPtr[0] == '_') && (CurrPtr[1] == 'S') && (CurrPtr[2] == '3') && (CurrPtr[3] == '_')) { + break; + } + // + // For iasl compiler version 20040527. + // + if ((CurrPtr[0] == '\\') && (CurrPtr[1] == '_') && (CurrPtr[2] == 'S') && (CurrPtr[3] == '3')) { + break; + } + } + CurrPtr++; + } + CurrPtr = (UINT8*) &((EFI_ACPI_DESCRIPTION_HEADER*) TableHeader)[0]; + EndPtr = (UINT8*) TableHeader; + EndPtr = EndPtr + TableHeader->Length; + while (CurrPtr < (EndPtr-2)) { + // + // For mipi dsi port select _DEP. + // + if (mSystemConfiguration.MipiDsi== 1) { + // + // For iasl compiler version 20061109. + // + if ((CurrPtr[0] == 'N') && (CurrPtr[1] == 'D') && (CurrPtr[2] == 'E') && (CurrPtr[3] == 'P')) { + CurrPtr[0] = '_'; + break; + } + + } else { + if ((CurrPtr[0] == 'P') && (CurrPtr[1] == 'D') && (CurrPtr[2] == 'E') && (CurrPtr[3] == 'P')) { + CurrPtr[0] = '_'; + break; + } + + } + CurrPtr++; + } + // + // 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) { + // + // GNVS operation region. + // + case (SIGNATURE_32 ('G', '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; + default: + break; + } + } + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatformHooks.h b/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatformHooks.h new file mode 100644 index 0000000000..164f45e6a3 --- /dev/null +++ b/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatformHooks.h @@ -0,0 +1,132 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + AcpiPlatformHooks.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_HOOKS_H_ +#define _ACPI_PLATFORM_HOOKS_H_ + +// +// Statements that include other header files +// + +#include +#include "Platform.h" +#include + +#define AML_NAME_OP 0x08 +#define AML_METHOD_OP 0x14 +#define AML_OPREGION_OP 0x80 +#define AML_PACKAGE_OP 0x12 // Package operator. +#define AML_NAME_PREFIX_SIZE 0x06 +#define AML_NAME_DWORD_SIZE 0x0C + +#pragma pack(1) + +typedef struct { + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT16 Flags; +} EFI_CPU_ID_MAP; + +typedef struct { + UINT8 StartByte; + UINT32 NameStr; + UINT8 Size; + UINT32 Value; +} EFI_ACPI_NAMEPACK_DWORD; + +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; + +typedef struct { + UINT8 PackageOp; + UINT8 PkgLeadByte; + UINT8 NumEntries; + UINT8 BytePrefix0; + UINT8 Entries; + UINT8 BytePrefix1; + UINT8 Revision; + UINT8 BytePrefix2; + UINT8 Domain; + UINT8 BytePrefix3; + UINT8 Coordinate; + UINT8 BytePrefix4; + UINT8 ProcNumber; +} EFI_PSD_PACKAGE; + +#pragma pack() + +#define ACPI_NAME_COMMAND_FROM_NAME_STR(a) BASE_CR (a, EFI_ACPI_NAME_COMMAND, NameStr) +#define ACPI_NAME_COMMAND_FROM_NAMEPACK_STR(a) BASE_CR (a, EFI_ACPI_NAMEPACK_DWORD, NameStr) + +EFI_STATUS +PlatformHookInit ( + VOID + ); + + +EFI_STATUS +PatchDsdtTable ( + IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader + ); + +EFI_STATUS +PatchGv3SsdtTable ( + IN OUT EFI_ACPI_DESCRIPTION_HEADER *Table + ); + +EFI_STATUS +PatchErstTable ( + IN OUT EFI_ACPI_DESCRIPTION_HEADER *Table + ); + +EFI_STATUS +AppendCpuMapTableEntry ( + IN EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE *AcpiLocalApic + ); + +#endif diff --git a/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatformHooksLib.h b/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatformHooksLib.h new file mode 100644 index 0000000000..f6a4b3b4d0 --- /dev/null +++ b/Vlv2TbltDevicePkg/AcpiPlatform/AcpiPlatformHooksLib.h @@ -0,0 +1,96 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + AcpiPlatformHooksLib.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_HOOKS_LIB_H_ +#define _ACPI_PLATFORM_HOOKS_LIB_H_ + +// +// Statements that include other header files. +// +#include + +/** + Returns the ACPI table version that the platform wants. + + @param[in] None + + @retval EFI_ACPI_TABLE_VERSION_NONE if ACPI is to be disabled. + @retval EFI_ACPI_TABLE_VERSION_1_0B if 1.0b. + @retval EFI_ACPI_TABLE_VERSION_2_00 if 2.00. +**/ +EFI_ACPI_TABLE_VERSION +AcpiPlatformHooksGetAcpiTableVersion ( + VOID + ); + +/** + Returns the OEMID, OEM Table ID, OEM Revision. + + @param[in] None + + @retval OemId OEM ID string for ACPI tables, maximum 6 ASCII characters. + This is an OEM-supplied string that identifies the OEM. + @retval OemTableId An OEM-supplied string that the OEM uses to identify + the particular data table. This field is particularly useful + when defining a definition block to distinguish definition block + functions. The OEM assigns each dissimilar table a new OEM Table ID. + @retval OemRevision An OEM-supplied revision number for ACPI tables. + Larger numbers are assumed to be newer revisions. + +**/ +EFI_STATUS +AcpiPlatformHooksGetOemFields ( + OUT UINT8 *OemId, + OUT UINT64 *OemTableId, + OUT UINT32 *OemRevision + ); + + /** + Called for every ACPI table found in the BIOS flash. + Returns whether a table is active or not. Inactive tables + are not published in the ACPI table list. This hook can be + used to implement optional SSDT tables or enabling/disabling + specific functionality (e.g. SPCR table) based on a setup + switch or platform preference. In case of optional SSDT tables, + the platform flash will include all the SSDT tables but will + return EFI_SUCCESS only for those tables that need to be + published. + This hook can also be used to update the table data. The header + is updated by the common code. For example, if a platform wants + to use an SSDT table to export some platform settings to the + ACPI code, it needs to update the data inside that SSDT based + on platform preferences in this hook. + + @param[in] None + + @retval EFI_SUCCESS if the table is active. + @retval EFI_UNSUPPORTED if the table is not active. +**/ +EFI_STATUS +AcpiPlatformHooksIsActiveTable ( + IN OUT EFI_ACPI_COMMON_HEADER *Table + ); + +#endif diff --git a/Vlv2TbltDevicePkg/AcpiPlatform/Osfr.h b/Vlv2TbltDevicePkg/AcpiPlatform/Osfr.h new file mode 100644 index 0000000000..1bef1afde0 --- /dev/null +++ b/Vlv2TbltDevicePkg/AcpiPlatform/Osfr.h @@ -0,0 +1,61 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + Osfr.h + +Abstract: + + This file describes the contents of the ACPI OSFR Table. + +--*/ + +#ifndef _OSFR_H +#define _OSFR_H + +// +// Statements that include other files. +// +#include +#include + +#pragma pack (1) + +#define EFI_ACPI_OSFR_TABLE_REVISION 0x1 +//#define EFI_ACPI_OSFR_TABLE_SIGNATURE 'RFSO' +#define EFI_ACPI_OSFR_TABLE_SIGNATURE SIGNATURE_32('O', 'S', 'F', 'R') //'RFSO' + +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 ObjectCount; + UINT32 TableDWORDs [64]; +} EFI_ACPI_OSFR_TABLE; + +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 ObjectCount; +} EFI_ACPI_OSFR_TABLE_FIXED_PORTION; + +typedef struct { + EFI_GUID ObjectUUID; + UINT32 Reserved1; + UINT32 ManufacturerNameStringOffset; + UINT32 ModelNameStringOffset; + UINT32 Reserved2; + UINT32 MicrosoftReferenceOffset; +} EFI_ACPI_OSFR_OCUR_OBJECT; + +#pragma pack () + +#endif diff --git a/Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.c b/Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.c new file mode 100644 index 0000000000..709cdc76ce --- /dev/null +++ b/Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.c @@ -0,0 +1,927 @@ +/** @file + +Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include "FirmwareUpdate.h" + +EFI_HII_HANDLE HiiHandle; + +// +// MinnowMax Flash Layout +// +//Start (hex) End (hex) Length (hex) Area Name +//----------- --------- ------------ --------- +//00000000 007FFFFF 00800000 Flash Image +// +//00000000 00000FFF 00001000 Descriptor Region +//00001000 004FFFFF 004FF000 TXE Region +//00500000 007FFFFF 00300000 BIOS Region +// +FV_REGION_INFO mRegionInfo[] = { + {FixedPcdGet32 (PcdFlashDescriptorBase), FixedPcdGet32 (PcdFlashDescriptorSize), TRUE}, + {FixedPcdGet32 (PcdTxeRomBase), FixedPcdGet32 (PcdTxeRomSize), TRUE}, + {FixedPcdGet32 (PcdBiosRomBase), FixedPcdGet32 (PcdBiosRomSize), TRUE} +}; + +UINTN mRegionInfoCount = sizeof (mRegionInfo) / sizeof (mRegionInfo[0]); + +FV_INPUT_DATA mInputData = {0}; + +EFI_SPI_PROTOCOL *mSpiProtocol; + +EFI_STATUS +GetRegionIndex ( + IN EFI_PHYSICAL_ADDRESS Address, + OUT UINTN *RegionIndex + ) +{ + UINTN Index; + + for (Index = 0; Index < mRegionInfoCount; Index++) { + if (Address >= mRegionInfo[Index].Base && + Address < (mRegionInfo[Index].Base + mRegionInfo[Index].Size) + ) { + break; + } + } + + *RegionIndex = Index; + if (Index >= mRegionInfoCount) { + return EFI_NOT_FOUND; + } + return EFI_SUCCESS; +} + +BOOLEAN +UpdateBlock ( + IN EFI_PHYSICAL_ADDRESS Address + ) +{ + EFI_STATUS Status; + UINTN Index; + + if (mInputData.FullFlashUpdate) { + return TRUE; + } + + Status = GetRegionIndex (Address, &Index); + if ((!EFI_ERROR(Status)) && mRegionInfo[Index].Update) { + return TRUE; + } + + return FALSE; +} + +EFI_STATUS +MarkRegionState ( + IN EFI_PHYSICAL_ADDRESS Address, + IN BOOLEAN Update + ) +{ + EFI_STATUS Status; + UINTN Index; + + Status = GetRegionIndex (Address, &Index); + if (!EFI_ERROR(Status)) { + mRegionInfo[Index].Update = Update; + } + + return Status; +} + +UINTN +InternalPrintToken ( + IN CONST CHAR16 *Format, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Console, + IN VA_LIST Marker + ) +{ + EFI_STATUS Status; + UINTN Return; + CHAR16 *Buffer; + UINTN BufferSize; + + ASSERT (Format != NULL); + ASSERT (((UINTN) Format & BIT0) == 0); + ASSERT (Console != NULL); + + BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16); + + Buffer = (CHAR16 *) AllocatePool(BufferSize); + ASSERT (Buffer != NULL); + + Return = UnicodeVSPrint (Buffer, BufferSize, Format, Marker); + + if (Console != NULL && Return > 0) { + // + // To be extra safe make sure Console has been initialized. + // + Status = Console->OutputString (Console, Buffer); + if (EFI_ERROR (Status)) { + Return = 0; + } + } + + FreePool (Buffer); + + return Return; +} + +UINTN +EFIAPI +PrintToken ( + IN UINT16 Token, + IN EFI_HII_HANDLE Handle, + ... + ) +{ + VA_LIST Marker; + UINTN Return; + CHAR16 *Format; + + VA_START (Marker, Handle); + + Format = HiiGetString (Handle, Token, NULL); + ASSERT (Format != NULL); + + Return = InternalPrintToken (Format, gST->ConOut, Marker); + + FreePool (Format); + + VA_END (Marker); + + return Return; +} + +EFI_STATUS +ParseCommandLine ( + IN UINTN Argc, + IN CHAR16 **Argv + ) +{ + EFI_STATUS Status; + UINTN Index; + + // + // Check to make sure that the command line has enough arguments for minimal + // operation. The minimum is just the file name. + // + if (Argc < 2 || Argc > 4) { + return EFI_INVALID_PARAMETER; + } + + // + // Loop through command line arguments. + // + for (Index = 1; Index < Argc; Index++) { + // + // Make sure the string is valid. + // + if (StrLen (Argv[Index]) == 0) {; + PrintToken (STRING_TOKEN (STR_FWUPDATE_ZEROLENGTH_ARG), HiiHandle); + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if this is an option or the file name. + // + if ((Argv[Index])[0] == L'-' || (Argv[Index])[0] == L'/') { + // + // Parse the arguments. + // + if ((StrCmp (Argv[Index], L"-h") == 0) || + (StrCmp (Argv[Index], L"--help") == 0) || + (StrCmp (Argv[Index], L"/?") == 0) || + (StrCmp (Argv[Index], L"/h") == 0)) { + // + // Print Help Information. + // + return EFI_INVALID_PARAMETER; + } else if (StrCmp (Argv[Index], L"-m") == 0) { + // + // Parse the MAC address here. + // + Status = ConvertMac(Argv[Index+1]); + if (EFI_ERROR(Status)) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_INVAILD_MAC), HiiHandle); + return Status; + } + + // + // Save the MAC address to mInputData.MacValue. + // + mInputData.UpdateMac= TRUE; + Index++; + } else { + // + // Invalid option was provided. + // + return EFI_INVALID_PARAMETER; + } + } + if ((Index == Argc - 1) && (StrCmp (Argv[Index - 1], L"-m") != 0)) { + // + // The only parameter that is not an option is the firmware image. Check + // to make sure that the file exists. + // + Status = ShellIsFile (Argv[Index]); + if (EFI_ERROR (Status)) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_FILE_NOT_FOUND_ERROR), HiiHandle, Argv[Index]); + return EFI_INVALID_PARAMETER; + } + if (StrLen (Argv[Index]) > INPUT_STRING_LEN) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_PATH_ERROR), HiiHandle, Argv[Index]); + return EFI_INVALID_PARAMETER; + } + StrCpy (mInputData.FileName, Argv[Index]); + mInputData.UpdateFromFile = TRUE; + } + } + + return EFI_SUCCESS; +} + +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ) +{ + EFI_STATUS Status; + UINTN Index; + UINT32 FileSize; + UINT32 BufferSize; + UINT8 *FileBuffer; + UINT8 *Buffer; + EFI_PHYSICAL_ADDRESS Address; + UINTN CountOfBlocks; + EFI_TPL OldTpl; + BOOLEAN ResetRequired; + BOOLEAN FlashError; + + Index = 0; + FileSize = 0; + BufferSize = 0; + FileBuffer = NULL; + Buffer = NULL; + Address = 0; + CountOfBlocks = 0; + ResetRequired = FALSE; + FlashError = FALSE; + + Status = EFI_SUCCESS; + + mInputData.FullFlashUpdate = TRUE; + + // + // Publish our HII data. + // + HiiHandle = HiiAddPackages ( + &gEfiCallerIdGuid, + NULL, + FirmwareUpdateStrings, + NULL + ); + if (HiiHandle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Locate the SPI protocol. + // + Status = gBS->LocateProtocol ( + &gEfiSpiProtocolGuid, + NULL, + (VOID **)&mSpiProtocol + ); + if (EFI_ERROR (Status)) { + PrintToken (STRING_TOKEN (STR_SPI_NOT_FOUND), HiiHandle); + return EFI_DEVICE_ERROR; + } + + // + // Parse the command line. + // + Status = ParseCommandLine (Argc, Argv); + if (EFI_ERROR (Status)) { + PrintHelpInfo (); + Status = EFI_SUCCESS; + goto Done; + } + + // + // Display sign-on information. + // + PrintToken (STRING_TOKEN (STR_FWUPDATE_FIRMWARE_VOL_UPDATE), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_VERSION), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_COPYRIGHT), HiiHandle); + + // + // Test to see if the firmware needs to be updated. + // + if (mInputData.UpdateFromFile) { + // + // Get the file to use in the update. + // + PrintToken (STRING_TOKEN (STR_FWUPDATE_READ_FILE), HiiHandle, mInputData.FileName); + Status = ReadFileData (mInputData.FileName, &FileBuffer, &FileSize); + if (EFI_ERROR (Status)) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_READ_FILE_ERROR), HiiHandle, mInputData.FileName); + goto Done; + } + + // + // Check that the file and flash sizes match. + // + if (FileSize != PcdGet32 (PcdFlashChipSize)) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_SIZE), HiiHandle); + Status = EFI_UNSUPPORTED; + goto Done; + } + + // + // Display flash update information. + // + PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATING_FIRMWARE), HiiHandle); + + // + // Update it. + // + Buffer = FileBuffer; + BufferSize = FileSize; + Address = PcdGet32 (PcdFlashChipBase); + CountOfBlocks = (UINTN) (BufferSize / BLOCK_SIZE); + + // + // Raise TPL to TPL_NOTIFY to block any event handler, + // while still allowing RaiseTPL(TPL_NOTIFY) within + // output driver during Print(). + // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + for (Index = 0; Index < CountOfBlocks; Index++) { + // + // Handle block based on address and contents. + // + if (!UpdateBlock (Address)) { + DEBUG((EFI_D_INFO, "Skipping block at 0x%lx\n", Address)); + } else if (!EFI_ERROR (InternalCompareBlock (Address, Buffer))) { + DEBUG((EFI_D_INFO, "Skipping block at 0x%lx (already programmed)\n", Address)); + } else { + // + // Display a dot for each block being updated. + // + Print (L"."); + + // + // Flag that the flash image will be changed and the system must be rebooted + // to use the change. + // + ResetRequired = TRUE; + + // + // Make updating process uninterruptable, + // so that the flash memory area is not accessed by other entities + // which may interfere with the updating process. + // + Status = InternalEraseBlock (Address); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR (Status)) { + gBS->RestoreTPL (OldTpl); + FlashError = TRUE; + goto Done; + } + Status = InternalWriteBlock ( + Address, + Buffer, + (BufferSize > BLOCK_SIZE ? BLOCK_SIZE : BufferSize) + ); + if (EFI_ERROR (Status)) { + gBS->RestoreTPL (OldTpl); + FlashError = TRUE; + goto Done; + } + } + + // + // Move to next block to update. + // + Address += BLOCK_SIZE; + Buffer += BLOCK_SIZE; + if (BufferSize > BLOCK_SIZE) { + BufferSize -= BLOCK_SIZE; + } else { + BufferSize = 0; + } + } + gBS->RestoreTPL (OldTpl); + + // + // Print result of update. + // + if (!FlashError) { + if (ResetRequired) { + Print (L"\n"); + PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATE_SUCCESS), HiiHandle); + } else { + PrintToken (STRING_TOKEN (STR_FWUPDATE_NO_RESET), HiiHandle); + } + } else { + goto Done; + } + } + + // + // All flash updates are done so see if the system needs to be reset. + // + if (ResetRequired && !FlashError) { + // + // Update successful. + // + for (Index = 5; Index > 0; Index--) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_SHUTDOWN), HiiHandle, Index); + gBS->Stall (1000000); + } + + gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL); + PrintToken (STRING_TOKEN (STR_FWUPDATE_MANUAL_RESET), HiiHandle); + CpuDeadLoop (); + } + +Done: + // + // Print flash update failure message if error detected. + // + if (FlashError) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATE_FAILED), HiiHandle, Index); + } + + // + // Do cleanup. + // + if (HiiHandle != NULL) { + HiiRemovePackages (HiiHandle); + } + if (FileBuffer) { + gBS->FreePool (FileBuffer); + } + + return Status; +} + +STATIC +EFI_STATUS +InternalEraseBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +/*++ + +Routine Description: + + Erase the whole block. + +Arguments: + + BaseAddress - Base address of the block to be erased. + +Returns: + + EFI_SUCCESS - The command completed successfully. + Other - Device error or wirte-locked, operation failed. + +--*/ +{ + EFI_STATUS Status; + UINTN NumBytes; + + NumBytes = BLOCK_SIZE; + + Status = SpiFlashBlockErase ((UINTN) BaseAddress, &NumBytes); + + return Status; +} + +#if 0 +STATIC +EFI_STATUS +InternalReadBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT VOID *ReadBuffer + ) +{ + EFI_STATUS Status; + UINT32 BlockSize; + + BlockSize = BLOCK_SIZE; + + Status = SpiFlashRead ((UINTN) BaseAddress, &BlockSize, ReadBuffer); + + return Status; +} +#endif + +STATIC +EFI_STATUS +InternalCompareBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + VOID *CompareBuffer; + UINT32 NumBytes; + INTN CompareResult; + + NumBytes = BLOCK_SIZE; + CompareBuffer = AllocatePool (NumBytes); + if (CompareBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + Status = SpiFlashRead ((UINTN) BaseAddress, &NumBytes, CompareBuffer); + if (EFI_ERROR (Status)) { + goto Done; + } + CompareResult = CompareMem (CompareBuffer, Buffer, BLOCK_SIZE); + if (CompareResult != 0) { + Status = EFI_VOLUME_CORRUPTED; + } + +Done: + if (CompareBuffer != NULL) { + FreePool (CompareBuffer); + } + + return Status; +} + +STATIC +EFI_STATUS +InternalWriteBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT8 *Buffer, + IN UINT32 BufferSize + ) +/*++ + +Routine Description: + + Write a block of data. + +Arguments: + + BaseAddress - Base address of the block. + Buffer - Data buffer. + BufferSize - Size of the buffer. + +Returns: + + EFI_SUCCESS - The command completed successfully. + EFI_INVALID_PARAMETER - Invalid parameter, can not proceed. + Other - Device error or wirte-locked, operation failed. + +--*/ +{ + EFI_STATUS Status; + + Status = SpiFlashWrite ((UINTN) BaseAddress, &BufferSize, Buffer); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR (Status)) { + DEBUG((EFI_D_ERROR, "\nFlash write error.")); + return Status; + } + + WriteBackInvalidateDataCacheRange ((VOID *) (UINTN) BaseAddress, BLOCK_SIZE); + + Status = InternalCompareBlock (BaseAddress, Buffer); + if (EFI_ERROR (Status)) { + DEBUG((EFI_D_ERROR, "\nError when writing to BaseAddress %lx with different at offset %x.", BaseAddress, Status)); + } else { + DEBUG((EFI_D_INFO, "\nVerified data written to Block at %lx is correct.", BaseAddress)); + } + + return Status; + +} + +STATIC +EFI_STATUS +ReadFileData ( + IN CHAR16 *FileName, + OUT UINT8 **Buffer, + OUT UINT32 *BufferSize + ) +{ + EFI_STATUS Status; + SHELL_FILE_HANDLE FileHandle; + UINT64 Size; + VOID *NewBuffer; + UINTN ReadSize; + + FileHandle = NULL; + NewBuffer = NULL; + Size = 0; + + Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = FileHandleIsDirectory (FileHandle); + if (!EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + goto Done; + } + + Status = FileHandleGetSize (FileHandle, &Size); + if (EFI_ERROR (Status)) { + goto Done; + } + + NewBuffer = AllocatePool ((UINTN) Size); + + ReadSize = (UINTN) Size; + Status = FileHandleRead (FileHandle, &ReadSize, NewBuffer); + if (EFI_ERROR (Status)) { + goto Done; + } else if (ReadSize != (UINTN) Size) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + +Done: + if (FileHandle != NULL) { + ShellCloseFile (&FileHandle); + } + + if (EFI_ERROR (Status)) { + if (NewBuffer != NULL) { + FreePool (NewBuffer); + } + } else { + *Buffer = NewBuffer; + *BufferSize = (UINT32) Size; + } + + return Status; +} + +STATIC +VOID +PrintHelpInfo ( + VOID + ) +/*++ + +Routine Description: + + Print out help information. + +Arguments: + + None. + +Returns: + + None. + +--*/ +{ + PrintToken (STRING_TOKEN (STR_FWUPDATE_FIRMWARE_VOL_UPDATE), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_VERSION), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_COPYRIGHT), HiiHandle); + + Print (L"\n"); + PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_1), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_2), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_3), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_4), HiiHandle); + + Print (L"\n"); +} + +/** + Read NumBytes bytes of data from the address specified by + PAddress into Buffer. + + @param[in] Address The starting physical address of the read. + @param[in,out] NumBytes On input, the number of bytes to read. On output, the number + of bytes actually read. + @param[out] Buffer The destination data buffer for the read. + + @retval EFI_SUCCESS Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashRead ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + OUT UINT8 *Buffer + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINTN Offset = 0; + + ASSERT ((NumBytes != NULL) && (Buffer != NULL)); + + Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase); + + Status = mSpiProtocol->Execute ( + mSpiProtocol, + 1, //SPI_READ, + 0, //SPI_WREN, + TRUE, + TRUE, + FALSE, + Offset, + BLOCK_SIZE, + Buffer, + EnumSpiRegionAll + ); + return Status; + +} + +/** + Write NumBytes bytes of data from Buffer to the address specified by + PAddresss. + + @param[in] Address The starting physical address of the write. + @param[in,out] NumBytes On input, the number of bytes to write. On output, + the actual number of bytes written. + @param[in] Buffer The source data buffer for the write. + + @retval EFI_SUCCESS Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashWrite ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + UINTN Offset; + UINT32 Length; + UINT32 RemainingBytes; + + ASSERT ((NumBytes != NULL) && (Buffer != NULL)); + ASSERT (Address >= (UINTN)PcdGet32 (PcdFlashChipBase)); + + Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase); + + ASSERT ((*NumBytes + Offset) <= (UINTN)PcdGet32 (PcdFlashChipSize)); + + Status = EFI_SUCCESS; + RemainingBytes = *NumBytes; + + while (RemainingBytes > 0) { + if (RemainingBytes > SIZE_4KB) { + Length = SIZE_4KB; + } else { + Length = RemainingBytes; + } + Status = mSpiProtocol->Execute ( + mSpiProtocol, + SPI_PROG, + SPI_WREN, + TRUE, + TRUE, + TRUE, + (UINT32) Offset, + Length, + Buffer, + EnumSpiRegionAll + ); + if (EFI_ERROR (Status)) { + break; + } + RemainingBytes -= Length; + Offset += Length; + Buffer += Length; + } + + // + // Actual number of bytes written. + // + *NumBytes -= RemainingBytes; + + return Status; +} + +/** + Erase the block starting at Address. + + @param[in] Address The starting physical address of the block to be erased. + This library assume that caller garantee that the PAddress + is at the starting address of this block. + @param[in] NumBytes On input, the number of bytes of the logical block to be erased. + On output, the actual number of bytes erased. + + @retval EFI_SUCCESS. Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashBlockErase ( + IN UINTN Address, + IN UINTN *NumBytes + ) +{ + EFI_STATUS Status; + UINTN Offset; + UINTN RemainingBytes; + + ASSERT (NumBytes != NULL); + ASSERT (Address >= (UINTN)PcdGet32 (PcdFlashChipBase)); + + Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase); + + ASSERT ((*NumBytes % SIZE_4KB) == 0); + ASSERT ((*NumBytes + Offset) <= (UINTN)PcdGet32 (PcdFlashChipSize)); + + Status = EFI_SUCCESS; + RemainingBytes = *NumBytes; + + while (RemainingBytes > 0) { + Status = mSpiProtocol->Execute ( + mSpiProtocol, + SPI_SERASE, + SPI_WREN, + FALSE, + TRUE, + FALSE, + (UINT32) Offset, + 0, + NULL, + EnumSpiRegionAll + ); + if (EFI_ERROR (Status)) { + break; + } + RemainingBytes -= SIZE_4KB; + Offset += SIZE_4KB; + } + + // + // Actual number of bytes erased. + // + *NumBytes -= RemainingBytes; + + return Status; +} + +EFI_STATUS +EFIAPI +ConvertMac ( + CHAR16 *Str + ) +{ + UINTN Index; + UINT8 Temp[MAC_ADD_STR_LEN]; + + if (Str == NULL) + return EFI_INVALID_PARAMETER; + + if (StrLen(Str) != MAC_ADD_STR_LEN) + return EFI_INVALID_PARAMETER; + + for (Index = 0; Index < MAC_ADD_STR_LEN; Index++) { + if (Str[Index] >= 0x30 && Str[Index] <= 0x39) { + Temp[Index] = (UINT8)Str[Index] - 0x30; + } else if (Str[Index] >= 0x41 && Str[Index] <= 0x46) { + Temp[Index] = (UINT8)Str[Index] - 0x37; + } else if (Str[Index] >= 0x61 && Str[Index] <= 0x66) { + Temp[Index] = (UINT8)Str[Index] - 0x57; + } else { + return EFI_INVALID_PARAMETER; + } + } + + for (Index = 0; Index < MAC_ADD_BYTE_COUNT; Index++) { + mInputData.MacValue[Index] = (Temp[2 * Index] << 4) + Temp[2 * Index + 1]; + } + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.h b/Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.h new file mode 100644 index 0000000000..6c1c4b676d --- /dev/null +++ b/Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.h @@ -0,0 +1,190 @@ +/** @file + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef _FIRMWARE_UPDATE_H_ +#define _FIRMWARE_UPDATE_H_ + +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Function Prototypes. +// +STATIC +EFI_STATUS +ReadFileData ( + IN CHAR16 *FileName, + OUT UINT8 **Buffer, + OUT UINT32 *BufferSize + ); + +STATIC +EFI_STATUS +InternalEraseBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ); + +#if 0 +STATIC +EFI_STATUS +InternalReadBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT VOID *ReadBuffer + ); +#endif + +STATIC +EFI_STATUS +InternalCompareBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT8 *Buffer + ); + +STATIC +EFI_STATUS +InternalWriteBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT8 *Buffer, + IN UINT32 BufferSize + ); + +STATIC +VOID +PrintHelpInfo ( + VOID + ); + +STATIC +EFI_STATUS +EFIAPI +SpiFlashRead ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + OUT UINT8 *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +SpiFlashWrite ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + IN UINT8 *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +SpiFlashBlockErase ( + IN UINTN Address, + IN UINTN *NumBytes + ); + +STATIC +EFI_STATUS +EFIAPI +ConvertMac ( + CHAR16 *Str + ); + +EFI_STATUS +InitializeFVUPDATE ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +// +// Flash specific definitions. +// - Should we use a PCD for this information? +// +#define BLOCK_SIZE SIZE_4KB + +// +// Flash region layout and update information. +// +typedef struct { + EFI_PHYSICAL_ADDRESS Base; + UINTN Size; + BOOLEAN Update; +} FV_REGION_INFO; + +// +// MAC Address information. +// +#define MAC_ADD_STR_LEN 12 +#define MAC_ADD_STR_SIZE (MAC_ADD_STR_LEN + 1) +#define MAC_ADD_BYTE_COUNT 6 +#define MAC_ADD_TMP_STR_LEN 2 +#define MAC_ADD_TMP_STR_SIZE (MAC_ADD_TMP_STR_LEN + 1) + +// +// Command Line Data. +// +#define INPUT_STRING_LEN 255 +#define INPUT_STRING_SIZE (INPUT_STRING_LEN + 1) +typedef struct { + BOOLEAN UpdateFromFile; + CHAR16 FileName[INPUT_STRING_SIZE]; + BOOLEAN UpdateMac; + UINT8 MacValue[MAC_ADD_BYTE_COUNT]; + BOOLEAN FullFlashUpdate; +} FV_INPUT_DATA; + +// +// Prefix Opcode Index on the host SPI controller. +// +typedef enum { + SPI_WREN, // Prefix Opcode 0: Write Enable. + SPI_EWSR, // Prefix Opcode 1: Enable Write Status Register. +} PREFIX_OPCODE_INDEX; + +// +// Opcode Menu Index on the host SPI controller. +// +typedef enum { + SPI_READ_ID, // Opcode 0: READ ID, Read cycle with address. + SPI_READ, // Opcode 1: READ, Read cycle with address. + SPI_RDSR, // Opcode 2: Read Status Register, No address. + SPI_WRDI_SFDP, // Opcode 3: Write Disable or Discovery Parameters, No address. + SPI_SERASE, // Opcode 4: Sector Erase (4KB), Write cycle with address. + SPI_BERASE, // Opcode 5: Block Erase (32KB), Write cycle with address. + SPI_PROG, // Opcode 6: Byte Program, Write cycle with address. + SPI_WRSR, // Opcode 7: Write Status Register, No address. +} SPI_OPCODE_INDEX; + +#endif diff --git a/Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf b/Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf new file mode 100644 index 0000000000..4e2ec32ac6 --- /dev/null +++ b/Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf @@ -0,0 +1,90 @@ +## @file +# Implements a Tunnel Mountain specific flash update program. This will allow +# users to update all regions of the flash as needed in a given update. +# +# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FirmwareUpdate + FILE_GUID = AEFAF26C-FB6D-4fef-AF7A-9D78FF201FCA + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = ShellCEntryLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = X64 +# + +[Sources] + FirmwareUpdateStrings.uni + FirmwareUpdate.c + FirmwareUpdate.h + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + IA32FamilyCpuPkg/IA32FamilyCpuPkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + CacheMaintenanceLib + DebugLib + FileHandleLib + #FlashDeviceLib + #SpiFlashCommonLib + MemoryAllocationLib + PcdLib + ShellCEntryLib + ShellLib + UefiApplicationEntryPoint + UefiBootServicesTableLib + UefiLib + UefiRuntimeServicesTableLib + +[Protocols] + gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiSpiProtocolGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize ## CONSUMES + +[FixedPcd] +# gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize +# gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase +# gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize +# gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase +# gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize +# gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + + gPlatformModuleTokenSpaceGuid.PcdFlashChipBase + gPlatformModuleTokenSpaceGuid.PcdFlashChipSize + gPlatformModuleTokenSpaceGuid.PcdFlashDescriptorBase + gPlatformModuleTokenSpaceGuid.PcdFlashDescriptorSize + gPlatformModuleTokenSpaceGuid.PcdTxeRomBase + gPlatformModuleTokenSpaceGuid.PcdTxeRomSize + gPlatformModuleTokenSpaceGuid.PcdBiosRomBase + gPlatformModuleTokenSpaceGuid.PcdBiosRomSize + +[BuildOptions] + MSFT:*_*_X64_CC_FLAGS = /Od + INTEL:*_*_X64_CC_FLAGS = /Od \ No newline at end of file diff --git a/Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdateStrings.uni b/Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdateStrings.uni new file mode 100644 index 0000000000000000000000000000000000000000..bbf497f82f0cc51a5d38cd05838df7108d9b56b4 GIT binary patch literal 7472 zcmc(kYfl?T6o%((EA>CDh$50SK$51nsH$XwAyzOTu%VY!7GMl+!A@-xlK$F!Ytj$> z32onJj)z&V*Jd$D)d!q~ecN+y^xM?R@7%K6cHgH^)r6$2Rf*{KMDN(sKGXBQXgAdlwBpD=9|~>P zooOZS-s!uJ)+d?)4g0h;Iu*6RJyd%B>r=fu)TrYTK{wFn>*jEWHyXD^Vc#9-mtD_2 z3TQ_pw%3_Q9jJf|yzNW5z*ExGxap?*O(%57U{pola~UhLJ^ zGh81CXIdYLL$2U&>5b_I)Ni#ai)vIdCe3$Rbuj$CJCp&K1}Vv6K?CXHnYS}+%cRTt zo|pBa`0q(WOG1#AeqS>O!rqj%jlNkFl@t9%nZ!}ey>MmW+L8rrx;6clTvg8%Ni~sN z>1&#;$j0g#mA$O%ZbN-p^T@;~L_Jhw(`BvL@su|;!j}1+Qx9FJ&Z%Ga&pbU$q1)4Y zsBZcl6St>T+aB45<}0EKjZMG%ww}Pw9DCNZmNo2Zt5&s^-G5a7Qg1+x50;0!7#C&t z!zG1ED; zoBv%)nqF|Lp3^z?M2L?2Q@?y`U)rw0X3cj^XAOO^r(L&%9jTNZGZj&*4rR*Bu4J{Y zKD`di5z)E!JN9;)<^xV*9J?o~#JsxpdU+Y^67AO(>N9sC8WuC^vc#sI@Eq3TVaQ^j z*n?+b-7zYR?@-m+j#^hVtD^JPz0y;VVo^Cf7uQ>|2`qa}wpP=g`K^c?#eN}Vlx%#NL#uXZY`y-zP6FtpqjGa*7 z>}y1im7Yl|{SE z1Y=#eVpTct)`D!od>d$qE%1b9^$Nzt_T}ZCUJl1*YY>$u;(?8;*Q!VH+lH7UN%}w^d(2? zd-E-;(f@xLR)q%%zSrNcUf0w&b}s9y|KQ~san35s)nV+i3jO-B1i`30Tk<2bSWcNx z-17EIyv24oN!pz@MxS9&v;5pz-H1iC~ng` zs**Tot|%YuDI-soPo502@c|j^$ObvbH|2X5US~lb#r2rY%%HknHAw#75N9Rnq#^6F z^J<>G7UQeqeG$pyg&lEd^&Mv@bZNF5b#J_yPNIiRmhS9t^6-z_W=DFNmsN4U^~Og< zczNxk#^2uZ0$<#cVP&!Mjdp8Mb-Kldj63QBSxFSP&<$DUbPWdCLk-`MPB#@1xx3*;jQgw6nz@JuW9@lYJaB@tQz7>)b{jhz$}Mqg zCtJ?q<5hgHvSRm15hbTOYKbKw-S@t4UXeZz&W1QvputOwtdSRy)=#^@PwlDCXo&p4OC7Xx>ppPkDFJDmD|nJL~x9vX^b)3_+Y!z>Xmjo`_R5f}%i{qX-UB40S6 oeB;ls{4XLazYz7~+VMN*Sz}MIlZGb%7 literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/BfmLib.exe b/Vlv2TbltDevicePkg/BfmLib.exe new file mode 100644 index 0000000000000000000000000000000000000000..4402a78456ae1018915ac4a1fce5d5d5de656652 GIT binary patch literal 499712 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�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 K9QaSjfqw%w5I}YS literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/BiosIdD.env b/Vlv2TbltDevicePkg/BiosIdD.env new file mode 100644 index 0000000000..a2631e12ec --- /dev/null +++ b/Vlv2TbltDevicePkg/BiosIdD.env @@ -0,0 +1,30 @@ +#/** @file +# This file is used to define the BIOS ID parameters of the build. +# This file is processed by GenBiosId. +# The BIOS ID format conforms to "BIOS Revision Identification Specification", Rev. 0.7, 6/27/2001. +# +# BIOS ID string format: +# $(BOARD_ID)$(BOARD_REV).$(OEM_ID).$(VERSION_MAJOR).$(BUILD_TYPE)$(VERSION_MINOR).YYMMDDHHMM +# All fields must have a fixed length. +# Example: "TRFTCRB1.86C.0008.D03.0506081529" +# +# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +BOARD_REV = 1 +OEM_ID = I32 +BUILD_TYPE = D + +BOARD_ID = BLAKCRB +VERSION_MAJOR = 0076 +VERSION_MINOR = 01 diff --git a/Vlv2TbltDevicePkg/BiosIdR.env b/Vlv2TbltDevicePkg/BiosIdR.env new file mode 100644 index 0000000000..051df7a3ce --- /dev/null +++ b/Vlv2TbltDevicePkg/BiosIdR.env @@ -0,0 +1,30 @@ +#/** @file +# This file is used to define the BIOS ID parameters of the build. +# This file is processed by GenBiosId. +# The BIOS ID format conforms to "BIOS Revision Identification Specification", Rev. 0.7, 6/27/2001. +# +# BIOS ID string format: +# $(BOARD_ID)$(BOARD_REV).$(OEM_ID).$(VERSION_MAJOR).$(BUILD_TYPE)$(VERSION_MINOR).YYMMDDHHMM +# All fields must have a fixed length. +# Example: "TRFTCRB1.86C.0008.D03.0506081529" +# +# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +BOARD_REV = 1 +OEM_ID = I32 +BUILD_TYPE = R + +BOARD_ID = BLAKCRB +VERSION_MAJOR = 0076 +VERSION_MINOR = 01 diff --git a/Vlv2TbltDevicePkg/BiosIdx64D.env b/Vlv2TbltDevicePkg/BiosIdx64D.env new file mode 100644 index 0000000000..585ba614f1 --- /dev/null +++ b/Vlv2TbltDevicePkg/BiosIdx64D.env @@ -0,0 +1,30 @@ +#/** @file +# This file is used to define the BIOS ID parameters of the build. +# This file is processed by GenBiosId. +# The BIOS ID format conforms to "BIOS Revision Identification Specification", Rev. 0.7, 6/27/2001. +# +# BIOS ID string format: +# $(BOARD_ID)$(BOARD_REV).$(OEM_ID).$(VERSION_MAJOR).$(BUILD_TYPE)$(VERSION_MINOR).YYMMDDHHMM +# All fields must have a fixed length. +# Example: "TRFTCRB1.86C.0008.D03.0506081529" +# +# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +BOARD_REV = 1 +OEM_ID = X64 +BUILD_TYPE = D + +VERSION_MAJOR = 0076 +VERSION_MINOR = 01 +BOARD_ID = BBAYCRB diff --git a/Vlv2TbltDevicePkg/BiosIdx64R.env b/Vlv2TbltDevicePkg/BiosIdx64R.env new file mode 100644 index 0000000000..961550f77b --- /dev/null +++ b/Vlv2TbltDevicePkg/BiosIdx64R.env @@ -0,0 +1,30 @@ +#/** @file +# This file is used to define the BIOS ID parameters of the build. +# This file is processed by GenBiosId. +# The BIOS ID format conforms to "BIOS Revision Identification Specification", Rev. 0.7, 6/27/2001. +# +# BIOS ID string format: +# $(BOARD_ID)$(BOARD_REV).$(OEM_ID).$(VERSION_MAJOR).$(BUILD_TYPE)$(VERSION_MINOR).YYMMDDHHMM +# All fields must have a fixed length. +# Example: "TRFTCRB1.86C.0008.D03.0506081529" +# +# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +BOARD_REV = 1 +OEM_ID = X64 +BUILD_TYPE = R + +VERSION_MAJOR = 0076 +VERSION_MINOR = 01 +BOARD_ID = BBAYCRB diff --git a/Vlv2TbltDevicePkg/BootScriptSaveDxe/BootScriptSaveDxe.inf b/Vlv2TbltDevicePkg/BootScriptSaveDxe/BootScriptSaveDxe.inf new file mode 100644 index 0000000000..94f8b0eb73 --- /dev/null +++ b/Vlv2TbltDevicePkg/BootScriptSaveDxe/BootScriptSaveDxe.inf @@ -0,0 +1,65 @@ +# +# +## @file +# Component description file for ScriptSave Lite module. +# +# This is an implementation of the Boot Script Save protocol. +# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BootScriptSaveDxe + FILE_GUID = 42BB673D-09F3-4e2e-9FEE-D081131DED5B + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializeScriptSave + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + ScriptSave.c + InternalBootScriptSave.h + + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + MdeModulePkg/MdeModulePkg.dec + + +[LibraryClasses] + PcdLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + MemoryAllocationLib + UefiDriverEntryPoint + BaseMemoryLib + DebugLib + BaseLib + S3BootScriptLib + +[Protocols] + gEfiBootScriptSaveProtocolGuid # PROTOCOL ALWAYS_PRODUCED + + +[Depex] + TRUE + diff --git a/Vlv2TbltDevicePkg/BootScriptSaveDxe/InternalBootScriptSave.h b/Vlv2TbltDevicePkg/BootScriptSaveDxe/InternalBootScriptSave.h new file mode 100644 index 0000000000..d76f4e4d8b --- /dev/null +++ b/Vlv2TbltDevicePkg/BootScriptSaveDxe/InternalBootScriptSave.h @@ -0,0 +1,107 @@ +/** @file +// +// + Internal header file for S3 Boot Script Saver driver. + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef _INTERNAL_BOOT_SCRIPT_SAVE_H_ +#define _INTERNAL_BOOT_SCRIPT_SAVE_H_ +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Adds a record into a specified Framework boot script table. + + This function is used to store a boot script record into a given boot + script table. If the table specified by TableName is nonexistent in the + system, a new table will automatically be created and then the script record + will be added into the new table. A boot script table can add new script records + until EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is called. Currently, the only + meaningful table name is EFI_ACPI_S3_RESUME_SCRIPT_TABLE. This function is + responsible for allocating necessary memory for the script. + + This function has a variable parameter list. The exact parameter list depends on + the OpCode that is passed into the function. If an unsupported OpCode or illegal + parameter list is passed in, this function returns EFI_INVALID_PARAMETER. + If there are not enough resources available for storing more scripts, this function returns + EFI_OUT_OF_RESOURCES. + + @param[in] This A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance. + @param[in] TableName Name of the script table. Currently, the only meaningful value is + EFI_ACPI_S3_RESUME_SCRIPT_TABLE. + @param[in] OpCode The operation code (opcode) number. + @param[in] ... Argument list that is specific to each opcode. + + @retval EFI_SUCCESS The operation succeeded. A record was added into the + specified script table. + @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported. + If the opcode is unknow or not supported because of the PCD + Feature Flags. + @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script. + +**/ +EFI_STATUS +EFIAPI +BootScriptWrite ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + IN UINT16 TableName, + IN UINT16 OpCode, + ... + ); + +/** + Closes the specified script table. + + This function closes the specified boot script table and returns the base address + of the table. It allocates a new pool to duplicate all the boot scripts in the specified + table. Once this function is called, the specified table will be destroyed after it is + copied into the allocated pool. As a result, any attempts to add a script record into a + closed table will cause a new table to be created. The base address of the allocated pool + will be returned in Address. After using the boot script table, the caller is responsible + for freeing the pool that is allocated by this function. If the boot script table, + such as EFI_ACPI_S3_RESUME_SCRIPT_TABLE, is required to be stored in a nonperturbed + memory region, the caller should copy the table into the nonperturbed memory region by itself. + + @param[in] This A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance. + @param[in] TableName Name of the script table. Currently, the only meaningful value is + EFI_ACPI_S3_RESUME_SCRIPT_TABLE. + @param[in] Address A pointer to the physical address where the table begins. + + @retval EFI_SUCCESS The table was successfully returned. + @retval EFI_NOT_FOUND The specified table was not created previously. + @retval EFI_OUT_OF_RESOURCE Memory is insufficient to hold the reorganized boot script table. + @retval EFI_UNSUPPORTED The table type is not EFI_ACPI_S3_RESUME_SCRIPT_TABLE. + +**/ +EFI_STATUS +EFIAPI +BootScriptCloseTable ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + IN UINT16 TableName, + OUT EFI_PHYSICAL_ADDRESS *Address + ); +#endif //_INTERNAL_BOOT_SCRIPT_SAVE_H_ diff --git a/Vlv2TbltDevicePkg/BootScriptSaveDxe/ScriptSave.c b/Vlv2TbltDevicePkg/BootScriptSaveDxe/ScriptSave.c new file mode 100644 index 0000000000..55f758c573 --- /dev/null +++ b/Vlv2TbltDevicePkg/BootScriptSaveDxe/ScriptSave.c @@ -0,0 +1,631 @@ +/** @file + Implementation for S3 Boot Script Saver driver. + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include "InternalBootScriptSave.h" + +EFI_HANDLE mHandle = NULL; +EFI_BOOT_SCRIPT_SAVE_PROTOCOL mS3ScriptSave = { + BootScriptWrite, + BootScriptCloseTable + }; + +/** + Internal function to add IO write opcode to the table. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptIoWrite ( + IN VA_LIST Marker + ) +{ + S3_BOOT_SCRIPT_LIB_WIDTH Width; + UINT64 Address; + UINTN Count; + UINT8 *Buffer; + + Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); + Address = VA_ARG (Marker, UINT64); + Count = VA_ARG (Marker, UINTN); + Buffer = VA_ARG (Marker, UINT8 *); + + return S3BootScriptSaveIoWrite (Width, Address, Count, Buffer); +} + +/** + Internal function to add IO read/write opcode to the table. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptIoReadWrite ( + IN VA_LIST Marker + ) +{ + S3_BOOT_SCRIPT_LIB_WIDTH Width; + UINT64 Address; + UINT8 *Data; + UINT8 *DataMask; + + Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); + Address = VA_ARG (Marker, UINT64); + Data = VA_ARG (Marker, UINT8 *); + DataMask = VA_ARG (Marker, UINT8 *); + + return S3BootScriptSaveIoReadWrite (Width, Address, Data, DataMask); +} + +/** + Internal function to add memory write opcode to the table. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptMemWrite ( + IN VA_LIST Marker + ) +{ + S3_BOOT_SCRIPT_LIB_WIDTH Width; + UINT64 Address; + UINTN Count; + UINT8 *Buffer; + + Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); + Address = VA_ARG (Marker, UINT64); + Count = VA_ARG (Marker, UINTN); + Buffer = VA_ARG (Marker, UINT8 *); + + return S3BootScriptSaveMemWrite (Width, Address, Count, Buffer); +} + +/** + Internal function to add memory read/write opcode to the table. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptMemReadWrite ( + IN VA_LIST Marker + ) +{ + S3_BOOT_SCRIPT_LIB_WIDTH Width; + UINT64 Address; + UINT8 *Data; + UINT8 *DataMask; + + Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); + Address = VA_ARG (Marker, UINT64); + Data = VA_ARG (Marker, UINT8 *); + DataMask = VA_ARG (Marker, UINT8 *); + + return S3BootScriptSaveMemReadWrite (Width, Address, Data, DataMask); +} + +/** + Internal function to add PciCfg write opcode to the table. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptPciCfgWrite ( + IN VA_LIST Marker + ) +{ + S3_BOOT_SCRIPT_LIB_WIDTH Width; + UINT64 Address; + UINTN Count; + UINT8 *Buffer; + + Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); + Address = VA_ARG (Marker, UINT64); + Count = VA_ARG (Marker, UINTN); + Buffer = VA_ARG (Marker, UINT8 *); + + return S3BootScriptSavePciCfgWrite (Width, Address, Count, Buffer); +} + +/** + Internal function to PciCfg read/write opcode to the table. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptPciCfgReadWrite ( + IN VA_LIST Marker + ) +{ + S3_BOOT_SCRIPT_LIB_WIDTH Width; + UINT64 Address; + UINT8 *Data; + UINT8 *DataMask; + + Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); + Address = VA_ARG (Marker, UINT64); + Data = VA_ARG (Marker, UINT8 *); + DataMask = VA_ARG (Marker, UINT8 *); + + return S3BootScriptSavePciCfgReadWrite (Width, Address, Data, DataMask); +} + +/** + Internal function to add PciCfg2 write opcode to the table. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptPciCfg2Write ( + IN VA_LIST Marker + ) +{ + S3_BOOT_SCRIPT_LIB_WIDTH Width; + UINT64 Address; + UINTN Count; + UINT8 *Buffer; + UINT16 Segment; + + Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); + Address = VA_ARG (Marker, UINT64); + Count = VA_ARG (Marker, UINTN); + Buffer = VA_ARG (Marker, UINT8 *); + Segment = VA_ARG (Marker, UINT16); + + return S3BootScriptSavePciCfg2Write (Width, Segment, Address, Count, Buffer); +} + +/** + Internal function to PciCfg2 read/write opcode to the table. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptPciCfg2ReadWrite ( + IN VA_LIST Marker + ) +{ + S3_BOOT_SCRIPT_LIB_WIDTH Width; + UINT16 Segment; + UINT64 Address; + UINT8 *Data; + UINT8 *DataMask; + + Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); + Address = VA_ARG (Marker, UINT64); + Segment = VA_ARG (Marker, UINT16); + Data = VA_ARG (Marker, UINT8 *); + DataMask = VA_ARG (Marker, UINT8 *); + + return S3BootScriptSavePciCfg2ReadWrite (Width, Segment, Address, Data, DataMask); +} + +/** + Internal function to add smbus excute opcode to the table. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptSmbusExecute ( + IN VA_LIST Marker + ) +{ + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + EFI_SMBUS_DEVICE_COMMAND Command; + EFI_SMBUS_OPERATION Operation; + BOOLEAN PecCheck; + VOID *Buffer; + UINTN *DataSize; + UINTN SmBusAddress; + + SlaveAddress.SmbusDeviceAddress = VA_ARG (Marker, UINTN); + Command = VA_ARG (Marker, EFI_SMBUS_DEVICE_COMMAND); + Operation = VA_ARG (Marker, EFI_SMBUS_OPERATION); + PecCheck = VA_ARG (Marker, BOOLEAN); + SmBusAddress = SMBUS_LIB_ADDRESS (SlaveAddress.SmbusDeviceAddress,Command,0,PecCheck); + DataSize = VA_ARG (Marker, UINTN *); + Buffer = VA_ARG (Marker, VOID *); + + return S3BootScriptSaveSmbusExecute (SmBusAddress, Operation, DataSize, Buffer); +} + +/** + Internal function to add stall opcode to the table. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptStall ( + IN VA_LIST Marker + ) +{ + UINT32 Duration; + + Duration = VA_ARG (Marker, UINT32); + + return S3BootScriptSaveStall (Duration); +} + +/** + Internal function to add Save jmp address according to DISPATCH_OPCODE. + We ignore "Context" parameter. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptDispatch ( + IN VA_LIST Marker + ) +{ + VOID *EntryPoint; + + EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS); + return S3BootScriptSaveDispatch (EntryPoint); +} + +/** + Internal function to add memory pool operation to the table. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptMemPoll ( + IN VA_LIST Marker + ) +{ + S3_BOOT_SCRIPT_LIB_WIDTH Width; + UINT64 Address; + UINT8 *BitMask; + UINT8 *BitValue; + UINTN Duration; + UINTN LoopTimes; + + Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); + Address = VA_ARG (Marker, UINT64); + BitMask = VA_ARG (Marker, UINT8 *); + BitValue = VA_ARG (Marker, UINT8 *); + Duration = (UINTN)VA_ARG (Marker, UINT64); + LoopTimes = (UINTN)VA_ARG (Marker, UINT64); + + return S3BootScriptSaveMemPoll (Width, Address, BitMask, BitValue, Duration, LoopTimes); +} + +/** + Internal function to add Save jmp address according to DISPATCH_OPCODE2. + The "Context" parameter is not ignored. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. + @retval EFI_SUCCESS Opcode is added. + +**/ +EFI_STATUS +BootScriptDispatch2 ( + IN VA_LIST Marker + ) +{ + VOID *EntryPoint; + VOID *Context; + + EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS); + Context = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS); + + return S3BootScriptSaveDispatch2 (EntryPoint, Context); +} + +/** + Internal function to add the opcode link node to the link list. + + @param Marker The variable argument list to get the opcode + and associated attributes. + + @retval EFI_OUT_OF_RESOURCES Not enought resource to complete the operations. + @retval EFI_SUCCESS The opcode entry is added to the link list + successfully. +**/ +EFI_STATUS +BootScriptInformation ( + IN VA_LIST Marker + ) +{ + UINT32 InformationLength; + EFI_PHYSICAL_ADDRESS Information; + + InformationLength = VA_ARG (Marker, UINT32); + Information = VA_ARG (Marker, EFI_PHYSICAL_ADDRESS); + return S3BootScriptSaveInformation (InformationLength, (VOID*)(UINTN)Information); +} + +/** + Adds a record into a specified Framework boot script table. + + This function is used to store a boot script record into a given boot + script table. If the table specified by TableName is nonexistent in the + system, a new table will automatically be created and then the script record + will be added into the new table. A boot script table can add new script records + until EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is called. Currently, the only + meaningful table name is EFI_ACPI_S3_RESUME_SCRIPT_TABLE. This function is + responsible for allocating necessary memory for the script. + + This function has a variable parameter list. The exact parameter list depends on + the OpCode that is passed into the function. If an unsupported OpCode or illegal + parameter list is passed in, this function returns EFI_INVALID_PARAMETER. + If there are not enough resources available for storing more scripts, this function returns + EFI_OUT_OF_RESOURCES. + + @param This A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance. + @param TableName Name of the script table. Currently, the only meaningful value is + EFI_ACPI_S3_RESUME_SCRIPT_TABLE. + @param OpCode The operation code (opcode) number. + @param ... Argument list that is specific to each opcode. + + @retval EFI_SUCCESS The operation succeeded. A record was added into the + specified script table. + @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported. + If the opcode is unknow or not supported because of the PCD + Feature Flags. + @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script. + +**/ +EFI_STATUS +EFIAPI +BootScriptWrite ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + IN UINT16 TableName, + IN UINT16 OpCode, + ... + ) +{ + EFI_STATUS Status; + VA_LIST Marker; + + if (TableName != FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE) { + // + // Only S3 boot script is supported for now. + // + return EFI_OUT_OF_RESOURCES; + } + + // + // Build script according to opcode. + // + switch (OpCode) { + + case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptIoWrite (Marker); + VA_END (Marker); + break; + + case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptIoReadWrite (Marker); + VA_END (Marker); + break; + + case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptMemWrite (Marker); + VA_END (Marker); + break; + + case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptMemReadWrite (Marker); + VA_END (Marker); + break; + + case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptPciCfgWrite (Marker); + VA_END (Marker); + break; + + case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptPciCfgReadWrite (Marker); + VA_END (Marker); + break; + + case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptSmbusExecute (Marker); + VA_END (Marker); + break; + + case EFI_BOOT_SCRIPT_STALL_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptStall (Marker); + VA_END (Marker); + + break; + + case EFI_BOOT_SCRIPT_DISPATCH_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptDispatch (Marker); + VA_END (Marker); + break; + + case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptDispatch2 (Marker); + VA_END (Marker); + break; + + case EFI_BOOT_SCRIPT_INFORMATION_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptInformation (Marker); + VA_END (Marker); + break; + + case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptMemPoll (Marker); + VA_END (Marker); + break; + + case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptPciCfg2Write (Marker); + VA_END (Marker); + break; + + case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE: + VA_START (Marker, OpCode); + Status = BootScriptPciCfg2ReadWrite (Marker); + VA_END (Marker); + break; + + default: + Status = EFI_INVALID_PARAMETER; + break; + } + + return Status; +} + +/** + Closes the specified script table. + + This function closes the specified boot script table and returns the base address + of the table. It allocates a new pool to duplicate all the boot scripts in the specified + table. Once this function is called, the specified table will be destroyed after it is + copied into the allocated pool. As a result, any attempts to add a script record into a + closed table will cause a new table to be created. The base address of the allocated pool + will be returned in Address. After using the boot script table, the caller is responsible + for freeing the pool that is allocated by this function. If the boot script table, + such as EFI_ACPI_S3_RESUME_SCRIPT_TABLE, is required to be stored in a nonperturbed + memory region, the caller should copy the table into the nonperturbed memory region by itself. + + @param This A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance. + @param TableName Name of the script table. Currently, the only meaningful value is + EFI_ACPI_S3_RESUME_SCRIPT_TABLE. + @param Address A pointer to the physical address where the table begins. + + @retval EFI_SUCCESS The table was successfully returned. + @retval EFI_NOT_FOUND The specified table was not created previously. + @retval EFI_OUT_OF_RESOURCE Memory is insufficient to hold the reorganized boot script table. + @retval EFI_UNSUPPORTED The table type is not EFI_ACPI_S3_RESUME_SCRIPT_TABLE. + +**/ +EFI_STATUS +EFIAPI +BootScriptCloseTable ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + IN UINT16 TableName, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + if (TableName != FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE) { + // + // Only S3 boot script is supported for now. + // + return EFI_NOT_FOUND; + } + *Address = (EFI_PHYSICAL_ADDRESS)(UINTN)S3BootScriptCloseTable (); + + if (*Address == 0) { + return EFI_NOT_FOUND; + } + return EFI_SUCCESS; +} + +/** + This routine is entry point of ScriptSave driver. + + @param ImageHandle Handle for this drivers loaded image protocol. + @param SystemTable EFI system table. + + @retval EFI_OUT_OF_RESOURCES No enough resource. + @retval EFI_SUCCESS Succesfully installed the ScriptSave driver. + @retval other Errors occured. + +**/ +EFI_STATUS +EFIAPI +InitializeScriptSave ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return gBS->InstallProtocolInterface ( + &mHandle, + &gEfiBootScriptSaveProtocolGuid, + EFI_NATIVE_INTERFACE, + &mS3ScriptSave + ); + +} + diff --git a/Vlv2TbltDevicePkg/Build_IFWI.bat b/Vlv2TbltDevicePkg/Build_IFWI.bat new file mode 100644 index 0000000000..a07a826df0 --- /dev/null +++ b/Vlv2TbltDevicePkg/Build_IFWI.bat @@ -0,0 +1,178 @@ +@REM @file +@REM Windows batch file to build BIOS ROM +@REM +@REM Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+@REM This program and the accompanying materials +@REM are licensed and made available under the terms and conditions of the BSD License +@REM which accompanies this distribution. The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php +@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 + +@echo off + +SetLocal EnableDelayedExpansion EnableExtensions + +@REM Go to root directory of the codebase. +cd .. + +:: Assign initial values +set exitCode=0 +set "Build_Flags= " +set "Stitch_Flags= " +set Arch=X64 +set PLATFORM_PACKAGE=Vlv2TbltDevicePkg +set ROOT_DIR=%CD% + +:: Parse Optional arguments +:OptLoop +if /i "%~1"=="/?" goto Usage + +if /i "%~1"=="/q" ( + set Build_Flags=%Build_Flags% /q + shift + goto OptLoop +) +if /i "%~1"=="/l" ( + set Build_Flags=%Build_Flags% /l + shift + goto OptLoop +) +if /i "%~1" == "/c" ( + set Build_Flags=%Build_Flags% /c + shift + goto OptLoop +) +if /i "%~1" == "/ECP" ( + set Build_Flags=%Build_Flags% /ecp + shift + goto OptLoop +) + +if /i "%~1"=="/s" ( + set Build_Flags=%Build_Flags% /s + shift + goto OptLoop +) + +if /i "%~1"=="/x64" ( + set Arch=X64 + set Build_Flags=%Build_Flags% /x64 + shift + goto OptLoop +) + +if /i "%~1"=="/IA32" ( + set Arch=IA32 + set Build_Flags=%Build_Flags% /IA32 + shift + goto OptLoop +) + +if /i "%~1"=="/nG" ( + set Stitch_Flags=%Stitch_Flags% /nG + shift + goto OptLoop +) +if /i "%~1"=="/nM" ( + set Stitch_Flags=%Stitch_Flags% /nM + shift + goto OptLoop +) +if /i "%~1"=="/nB" ( + set Stitch_Flags=%Stitch_Flags% /nB + shift + goto OptLoop +) + +:: Require 2 input parameters +if "%~2"=="" goto Usage + +:: Assign required arguments +set Platform_Type=%~1 +set Build_Target=%~2 +if "%~3"=="" ( + set "IFWI_Suffix= " +) else set "IFWI_Suffix=/S %~3" + +:: Build BIOS +echo ====================================================================== +echo Build_IFWI: Calling BIOS build Script... +if "%Platform_Type%" == "BYTC" ( + call %PLATFORM_PACKAGE%\bld_vlv_cr.bat %Build_Flags% %Platform_Type% %Build_Target% + +) else ( + call %PLATFORM_PACKAGE%\bld_vlv.bat %Build_Flags% %Platform_Type% %Build_Target% +) +if %ERRORLEVEL% NEQ 0 ( + echo echo -- Error Building BIOS & echo. + set exitCode=1 + goto exit +) +echo. +echo Finished Building BIOS. +@REM Set BIOS_ID environment variable here. +call Conf\BiosId.bat +echo BIOS_ID=%BIOS_ID% + +:: Set the Board_Id, Build_Type, Version_Major, and Version_Minor environment variables +find /v "#" Conf\BiosId.env > ver_strings +for /f "tokens=1,3" %%i in (ver_strings) do set %%i=%%j +del /f/q ver_strings >nul +set BIOS_Name=%BOARD_ID%_%Arch%_%BUILD_TYPE%_%VERSION_MAJOR%_%VERSION_MINOR%.ROM + +:: Start Integration process +echo ====================================================================== +echo Build_IFWI: Calling IFWI Stitching Script... +if "%Platform_Type%" == "BYTC" ( + pushd %PLATFORM_PACKAGE%\Stitch_CR +) else ( + pushd %PLATFORM_PACKAGE%\Stitch +) + :: IFWIStitch.bat [/nG] [/nM] [/nB] [/B BIOS.rom] [/C StitchConfig] [/S IFWISuffix] + call IFWIStitch.bat %Stitch_Flags% /B ..\..\%BIOS_Name% %IFWI_Suffix% + + @echo off +popd +if %ERRORLEVEL% NEQ 0 ( + echo echo -- Error Stitching %BIOS_Nam% & echo. + set exitCode=1 +) +echo. +echo Build_IFWI is finished. +echo The final IFWI file is located in %ROOT_DIR%\Vlv2TbltDevicePkg\Stitch\ +echo ====================================================================== +goto Exit + +:Usage +echo Script to build BIOS firmware and stitch the entire IFWI. +echo. +echo Usage: Build_IFWI.bat [options] PlatformType BuildTarget [IFWI Suffix] +echo. +echo /q Quiet mode. Only display Fatal Errors (slightly faster) +echo /l Log a copy of the build output to EDK2.log +echo /c CleanAll before building +echo /ecp ECP build enable +echo /src Build silicon source code (default binary) +echo /x64 Set Arch to X64 (default: X64) +echo /IA32 Set Arch to IA32 (default: X64) +echo /nG Do NOT update the GOP driver when stitching (ie keep src version) +echo /nM Do NOT update the Microcode when stitching (ie keep src version) +echo /nB Do NOT create a backup of BIOS.ROM before modifying it for Stitch +echo. +echo Platform Types: MNW2 +echo Build Targets: Release, Debug +echo IFWI Suffix: Suffix to append to end of IFWI filename (default: MM_DD_YYYY) +echo. +echo See Stitch/Stitch_Config.txt for additional stitching settings. +echo. +set exitCode=1 + +:Exit +@REM CD to platform package. +cd %ROOT_DIR%\Vlv2TbltDevicePkg +exit /b %exitCode% + +EndLocal diff --git a/Vlv2TbltDevicePkg/Build_IFWI.sh b/Vlv2TbltDevicePkg/Build_IFWI.sh new file mode 100644 index 0000000000..9bde502078 --- /dev/null +++ b/Vlv2TbltDevicePkg/Build_IFWI.sh @@ -0,0 +1,101 @@ +##********************************************************************** +## Function define +##********************************************************************** +function Usage ( ) { + echo + echo "Script to build BIOS firmware and stitch the entire IFWI." + echo + echo "Usage: Build_IFWI.bat PlatformType BuildTarget " + echo + echo + echo " Platform Types: MNW2" + echo " Build Targets: Release, Debug" + echo + echo " See Stitch/Stitch_Config.txt for additional stitching settings." + echo + echo + echo "Press any key......" + read + exit 0 +} + +## Assign initial values +exitCode=0 +Build_Flags= +Stitch_Flags= +Arch=X64 +PLATFORM_PACKAGE=Vlv2TbltDevicePkg + +## Parse Optional arguments +if [ "$1" == "/?" ]; then + Usage +fi + +for (( i=1; i<=$#; )) + do + if [ "$(echo $1 | tr 'a-z' 'A-Z')" == "/Q" ]; then + Build_Flags="$Build_Flags /q" + shift + elif [ "$(echo $1 | tr 'a-z' 'A-Z')" == "/L" ]; then + Build_Flags="$Build_Flags /l" + shift + elif [ "$(echo $1 | tr 'a-z' 'A-Z')" == "/C" ]; then + Build_Flags="$Build_Flags /c" + shift + elif [ "$(echo $1 | tr 'a-z' 'A-Z')" == "/ECP" ]; then + Build_Flags="$Build_Flags /ecp" + shift + elif [ "$(echo $1 | tr 'a-z' 'A-Z')" == "/X64" ]; then + Arch=X64 + Build_Flags="$Build_Flags /x64" + shift + elif [ "$1" == "/nG" ]; then + Stitch_Flags="$Stitch_Flags /nG" + shift + elif [ "$1" == "/nM" ]; then + Stitch_Flags="$Stitch_Flags /nM" + shift + elif [ "$1" == "/nB" ]; then + Stitch_Flags="$Stitch_Flags /nB" + shift + elif [ "$1" == "/nV" ]; then + Stitch_Flags="$Stitch_Flags /nV" + shift + else + break + fi + done + +## Require 2 input parameters +if [ "$2" == "" ]; then + Usage +fi + +## Assign required arguments +Platform_Type=$1 +Build_Target=$2 +if [ "$3" == "" ]; then + IFWI_Suffix= +else + IFWI_Suffix="/S $3" +fi + +## Go to root directory +cd .. + +## Build BIOS +echo "======================================================================" +echo "Build_IFWI: Calling BIOS build Script..." +./$PLATFORM_PACKAGE/bld_vlv.sh $Build_Flags $Platform_Type $Build_Target + +echo +echo Finished Building BIOS. + +## Start Integration process +echo ====================================================================== +echo Skip "Build_IFWI: Calling IFWI Stitching Script..." + +echo +echo Build_IFWI is finished. +echo The final IFWI file is located in Stitch +echo ====================================================================== diff --git a/Vlv2TbltDevicePkg/FCE.exe b/Vlv2TbltDevicePkg/FCE.exe new file mode 100644 index 0000000000000000000000000000000000000000..2b787be830318b2c56b5b35eadf8bbe8dd266d31 GIT binary patch literal 630784 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 literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.c b/Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.c new file mode 100644 index 0000000000..9fd3cb7788 --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.c @@ -0,0 +1,48 @@ +/** @file + This PEIM will parse the hoblist from fsp and report them into pei core. + This file contains the main entrypoint of the PEIM. + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include +#include + +static EFI_PEI_PPI_DESCRIPTOR mPpiList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiMasterBootModePpiGuid, + NULL + }, +}; + +/** + 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 +BootModePeiEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + (*PeiServices)->SetBootMode(PeiServices, BOOT_WITH_FULL_CONFIGURATION); + + (*PeiServices)->InstallPpi (PeiServices, &mPpiList[0]); + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.inf b/Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.inf new file mode 100644 index 0000000000..40dbba7de8 --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.inf @@ -0,0 +1,45 @@ +## @file +# FSP PEI Module +# +# Parses the hoblist from fsp and report them into pei core. It will install +# the memory as required. +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BootModePeim + FILE_GUID = 2B1D0832-2184-4C8F-A90D-8E4AF9DE5BCD + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = BootModePeiEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 +# + +[Sources] + BootModePei.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PeimEntryPoint + +[Ppis] + gEfiPeiMasterBootModePpiGuid + +[Depex] + TRUE diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/PeiFspHobProcessLibVlv2/FspHobProcessLibVlv2.c b/Vlv2TbltDevicePkg/FspSupport/Library/PeiFspHobProcessLibVlv2/FspHobProcessLibVlv2.c new file mode 100644 index 0000000000..944255349c --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/PeiFspHobProcessLibVlv2/FspHobProcessLibVlv2.c @@ -0,0 +1,387 @@ +/** @file + Null instance of Platform Sec Lib. + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +EFI_GUID gFspReservedMemoryResourceHobTsegGuid = {0xd038747c, 0xd00c, 0x4980, {0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55}}; + +// +// Additional pages are used by DXE memory manager. +// It should be consistent between RetrieveRequiredMemorySize() and GetPeiMemSize() +// +#define PEI_ADDITIONAL_MEMORY_SIZE (16 * EFI_PAGE_SIZE) + +/** + Get the mem size in memory type infromation table. + + @param PeiServices PEI Services table. + + @return the mem size in memory type infromation table. +**/ +UINT64 +GetMemorySizeInMemoryTypeInformation ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS Hob; + EFI_MEMORY_TYPE_INFORMATION *MemoryData; + UINT8 Index; + UINTN TempPageNum; + + MemoryData = NULL; + Status = (*PeiServices)->GetHobList (PeiServices, (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); + } + + if (MemoryData == NULL) { + return 0; + } + + TempPageNum = 0; + for (Index = 0; MemoryData[Index].Type != EfiMaxMemoryType; Index++) { + // + // Accumulate default memory size requirements + // + TempPageNum += MemoryData[Index].NumberOfPages; + } + + return TempPageNum * EFI_PAGE_SIZE; +} + +/** + Get the mem size need to be reserved in PEI phase. + + @param PeiServices PEI Services table. + + @return the mem size need to be reserved in PEI phase. +**/ +UINT64 +RetrieveRequiredMemorySize ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ + UINT64 Size; + + Size = GetMemorySizeInMemoryTypeInformation (PeiServices); + return Size + PEI_ADDITIONAL_MEMORY_SIZE; +} + +/** + Get the mem size need to be consumed and reserved in PEI phase. + + @param PeiServices PEI Services table. + @param BootMode Current boot mode. + + @return the mem size need to be consumed and reserved in PEI phase. +**/ +UINT64 +GetPeiMemSize ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT32 BootMode + ) +{ + UINT64 Size; + UINT64 MinSize; + + if (BootMode == BOOT_IN_RECOVERY_MODE) { + return PcdGet32 (PcdPeiRecoveryMinMemSize); + } + + Size = GetMemorySizeInMemoryTypeInformation (PeiServices); + + if (BootMode == BOOT_ON_FLASH_UPDATE) { + // + // Maybe more size when in CapsuleUpdate phase ? + // + MinSize = PcdGet32 (PcdPeiMinMemSize); + } else { + MinSize = PcdGet32 (PcdPeiMinMemSize); + } + + return MinSize + Size + PEI_ADDITIONAL_MEMORY_SIZE; +} + +/** + BIOS process FspBobList. + + @param FspHobList Pointer to the HOB data structure produced by FSP. + + @return If platform process the FSP hob list successfully. +**/ +EFI_STATUS +EFIAPI +FspHobProcess ( + IN VOID *FspHobList + ) +{ + EFI_PEI_HOB_POINTERS Hob; + UINT64 LowMemorySize; + UINT64 FspMemorySize; + EFI_PHYSICAL_ADDRESS FspMemoryBase; + UINT64 PeiMemSize; + EFI_PHYSICAL_ADDRESS PeiMemBase; + UINT64 S3PeiMemSize; + EFI_PHYSICAL_ADDRESS S3PeiMemBase; + BOOLEAN FoundFspMemHob; + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + PEI_CAPSULE_PPI *Capsule; + VOID *CapsuleBuffer; + UINTN CapsuleBufferLength; + UINT64 RequiredMemSize; + EFI_PEI_SERVICES **PeiServices; + UINT64 TsegSize; + EFI_PHYSICAL_ADDRESS TsegBase; + BOOLEAN FoundTsegHob; + + PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (); + + PeiServicesGetBootMode (&BootMode); + + PeiMemBase = 0; + LowMemorySize = 0; + FspMemorySize = 0; + FspMemoryBase = 0; + FoundFspMemHob = FALSE; + TsegSize = 0; + TsegBase = 0; + FoundTsegHob = FALSE; + + // + // Parse the hob list from fsp + // Report all the resource hob except the memory between 1M and 4G + // + Hob.Raw = (UINT8 *)(UINTN)FspHobList; + DEBUG((DEBUG_INFO, "FspHobList - 0x%x\n", FspHobList)); + + while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw)) != NULL) { + DEBUG((DEBUG_INFO, "\nResourceType: 0x%x\n", Hob.ResourceDescriptor->ResourceType)); + if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) || + (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED)) { + DEBUG((DEBUG_INFO, "ResourceAttribute: 0x%x\n", Hob.ResourceDescriptor->ResourceAttribute)); + DEBUG((DEBUG_INFO, "PhysicalStart: 0x%x\n", Hob.ResourceDescriptor->PhysicalStart)); + DEBUG((DEBUG_INFO, "ResourceLength: 0x%x\n", Hob.ResourceDescriptor->ResourceLength)); + DEBUG((DEBUG_INFO, "Owner: %g\n\n", &Hob.ResourceDescriptor->Owner)); + } + + if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) // Found the low memory length below 4G + && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB) + && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB)) { + LowMemorySize += Hob.ResourceDescriptor->ResourceLength; + Hob.Raw = GET_NEXT_HOB (Hob); + continue; + } + + if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) // Found the low memory length below 4G + && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB) + && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB) + && (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobGuid))) { + FoundFspMemHob = TRUE; + FspMemoryBase = Hob.ResourceDescriptor->PhysicalStart; + FspMemorySize = Hob.ResourceDescriptor->ResourceLength; + DEBUG((DEBUG_INFO, "Find fsp mem hob, base 0x%x, len 0x%x\n", FspMemoryBase, FspMemorySize)); + } + + if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) // Found the low memory length below 4G + && (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) + && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= 0x100000000) + && (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobTsegGuid))) { + FoundTsegHob = TRUE; + TsegBase = Hob.ResourceDescriptor->PhysicalStart; + + + if ((Hob.ResourceDescriptor->ResourceLength == 0 ) || (Hob.ResourceDescriptor->ResourceLength > 0x800000)){ + Hob.ResourceDescriptor->ResourceLength = 0x800000; + } + + + TsegSize = Hob.ResourceDescriptor->ResourceLength; + DEBUG((EFI_D_ERROR, "Find Tseg mem hob, base 0x%lx, len 0x%lx\n", TsegBase, TsegSize)); + } + + // + // Report the resource hob + // + BuildResourceDescriptorHob ( + Hob.ResourceDescriptor->ResourceType, + Hob.ResourceDescriptor->ResourceAttribute, + Hob.ResourceDescriptor->PhysicalStart, + Hob.ResourceDescriptor->ResourceLength + ); + + Hob.Raw = GET_NEXT_HOB (Hob); + } + + if (!FoundFspMemHob) { + DEBUG((DEBUG_INFO, "Didn't find the fsp used memory information.\n")); + //ASSERT(FALSE); + } + + DEBUG((DEBUG_INFO, "LowMemorySize: 0x%x.\n", LowMemorySize)); + DEBUG((DEBUG_INFO, "FspMemoryBase: 0x%x.\n", FspMemoryBase)); + DEBUG((DEBUG_INFO, "FspMemorySize: 0x%x.\n", FspMemorySize)); + + if (BootMode == BOOT_ON_S3_RESUME) { + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ( + 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 + ), + BASE_1MB, + LowMemorySize + ); + + Status = GetS3MemoryInfo (&S3PeiMemBase, &S3PeiMemSize); + ASSERT_EFI_ERROR (Status); + DEBUG((DEBUG_INFO, "S3 memory %Xh - %Xh bytes\n", S3PeiMemBase, S3PeiMemSize)); + + // + // Make sure Stack and PeiMemory are not overlap - JYAO1 + // + + Status = PeiServicesInstallPeiMemory ( + S3PeiMemBase, + S3PeiMemSize + ); + ASSERT_EFI_ERROR (Status); + } else { + PeiMemSize = GetPeiMemSize (PeiServices, BootMode); + DEBUG((DEBUG_INFO, "PEI memory size = %Xh bytes\n", PeiMemSize)); + + // + // Capsule mode + // + Capsule = NULL; + CapsuleBuffer = NULL; + CapsuleBufferLength = 0; + if (BootMode == BOOT_ON_FLASH_UPDATE) { + Status = PeiServicesLocatePpi ( + &gPeiCapsulePpiGuid, + 0, + NULL, + (VOID **) &Capsule + ); + ASSERT_EFI_ERROR (Status); + + if (Status == EFI_SUCCESS) { + // + // Make sure Stack and CapsuleBuffer are not overlap - JYAO1 + // + CapsuleBuffer = (VOID *)(UINTN)BASE_1MB; + CapsuleBufferLength = (UINTN)(LowMemorySize - PeiMemSize); + // + // Call the Capsule PPI Coalesce function to coalesce the capsule data. + // + Status = Capsule->Coalesce (PeiServices, &CapsuleBuffer, &CapsuleBufferLength); + } + } + + RequiredMemSize = RetrieveRequiredMemorySize (PeiServices); + DEBUG((DEBUG_INFO, "Required memory size = %Xh bytes\n", RequiredMemSize)); + + // + // Report the main memory + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ( + 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 + ), + BASE_1MB, + LowMemorySize + ); + + // + // Make sure Stack and CapsuleBuffer are not overlap - JYAO1 + // + + // + // Install efi memory + // + PeiMemBase = BASE_1MB + LowMemorySize - PeiMemSize; + Status = PeiServicesInstallPeiMemory ( + PeiMemBase, + PeiMemSize - RequiredMemSize + ); + ASSERT_EFI_ERROR (Status); + + if (Capsule != NULL) { + Status = Capsule->CreateState (PeiServices, CapsuleBuffer, CapsuleBufferLength); + } + } + + // + // Report GUIDed HOB for reserving SMRAM regions + // + if (FoundTsegHob) { + EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock; + + SmramHobDescriptorBlock = BuildGuidHob ( + &gEfiSmmPeiSmramMemoryReserveGuid, + sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK) + ); + ASSERT (SmramHobDescriptorBlock != NULL); + + SmramHobDescriptorBlock->NumberOfSmmReservedRegions = 1; + + SmramHobDescriptorBlock->Descriptor[0].PhysicalStart = TsegBase; + SmramHobDescriptorBlock->Descriptor[0].CpuStart = TsegBase; + SmramHobDescriptorBlock->Descriptor[0].PhysicalSize = TsegSize; + SmramHobDescriptorBlock->Descriptor[0].RegionState = EFI_SMRAM_CLOSED; + } + // + // NV Storage Hob + // + // + // Other hob for platform + // + PlatformHobCreateFromFsp ( PeiServices, FspHobList); + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/PeiFspHobProcessLibVlv2/FspHobProcessLibVlv2.inf b/Vlv2TbltDevicePkg/FspSupport/Library/PeiFspHobProcessLibVlv2/FspHobProcessLibVlv2.inf new file mode 100644 index 0000000000..909285f2e7 --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/PeiFspHobProcessLibVlv2/FspHobProcessLibVlv2.inf @@ -0,0 +1,79 @@ +## @file +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiFspHobProcessLibVlv2 + FILE_GUID = C7B7070B-E5A8-4b86-9110-BDCA1095F496 + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + LIBRARY_CLASS = FspHobProcessLib + +# +# 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] + FspHobProcessLibVlv2.c + + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + IntelFspPkg/IntelFspPkg.dec + IntelFspWrapperPkg/IntelFspWrapperPkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + HobLib + DebugLib + FspPlatformInfoLib + PeiServicesLib + PeiServicesTablePointerLib + PlatformFspLib + +[Pcd] + gFspWrapperTokenSpaceGuid.PcdPeiMinMemSize + gFspWrapperTokenSpaceGuid.PcdPeiRecoveryMinMemSize + +[Guids] + gFspReservedMemoryResourceHobGuid + gEfiMemoryTypeInformationGuid + gEfiSmmPeiSmramMemoryReserveGuid + +[Ppis] + gPeiCapsulePpiGuid diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/FspPlatformSecLibVlv2.c b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/FspPlatformSecLibVlv2.c new file mode 100644 index 0000000000..7a7931bebf --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/FspPlatformSecLibVlv2.c @@ -0,0 +1,150 @@ +/** @file + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include + +#include + +/** + 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 + ); + +/** + This interface conveys performance information out of the Security (SEC) phase into PEI. + + This service is published by the SEC phase. The SEC phase handoff has an optional + EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the + PEI Foundation. As such, if the platform supports collecting performance data in SEC, + this information is encapsulated into the data structure abstracted by this service. + This information is collected for the boot-strap processor (BSP) on IA-32. + + @param[in] PeiServices The pointer to the PEI Services Table. + @param[in] This The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI. + @param[out] Performance The pointer to performance data collected in SEC phase. + + @retval EFI_SUCCESS The data was successfully returned. + +**/ +EFI_STATUS +EFIAPI +SecGetPerformance ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN PEI_SEC_PERFORMANCE_PPI *This, + OUT FIRMWARE_SEC_PERFORMANCE *Performance + ); + +/** + 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 + ); + +EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPpi = { + SecPlatformInformation +}; + +PEI_SEC_PERFORMANCE_PPI mSecPerformancePpi = { + SecGetPerformance +}; + +EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = { + SecTemporaryRamSupport +}; + +EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformPpi[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiSecPlatformInformationPpiGuid, + &mSecPlatformInformationPpi + }, + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gPeiSecPerformancePpiGuid, + &mSecPerformancePpi + }, + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiTemporaryRamSupportPpiGuid, + &gSecTemporaryRamSupportPpi + }, +}; + +/** + 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 + ) +{ + EFI_PEI_PPI_DESCRIPTOR *PpiList; + + InitializeApicTimer (0, (UINT32) -1, TRUE, 5); + + PpiList = &mPeiSecPlatformPpi[0]; + + return PpiList; +} diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/FspPlatformSecLibVlv2.inf b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/FspPlatformSecLibVlv2.inf new file mode 100644 index 0000000000..3d9b1354ea --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/FspPlatformSecLibVlv2.inf @@ -0,0 +1,87 @@ +## @file +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SecPeiFspPlatformSecLibVlv2 + FILE_GUID = 6653876C-F6A1-45BB-A027-20455093BC6D + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + LIBRARY_CLASS = FspPlatformSecLib + +# +# 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] + FspPlatformSecLibVlv2.c + SecRamInitData.c + SaveSecContext.c + SecPlatformInformation.c + SecGetPerformance.c + SecTempRamSupport.c + PlatformInit.c + UartInit.c + +[Sources.IA32] + Ia32/SecEntry.asm + Ia32/PeiCoreEntry.asm + Ia32/AsmSaveSecContext.asm + Ia32/Stack.asm + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + IntelFspWrapperPkg/IntelFspWrapperPkg.dec + +[LibraryClasses] + LocalApicLib + SerialPortLib + +[Ppis] + gEfiSecPlatformInformationPpiGuid + gPeiSecPerformancePpiGuid + gEfiTemporaryRamSupportPpiGuid + +[Pcd] + gFspWrapperTokenSpaceGuid.PcdPeiTemporaryRamStackSize + gFspWrapperTokenSpaceGuid.PcdFlashFvFspBase + gFspWrapperTokenSpaceGuid.PcdFlashFvFspSize + +[FixedPcd] + gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchAddress + gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize + gFspWrapperTokenSpaceGuid.PcdFlashMicroCodeOffset + gFspWrapperTokenSpaceGuid.PcdFlashCodeCacheAddress + gFspWrapperTokenSpaceGuid.PcdFlashCodeCacheSize diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/AsmSaveSecContext.asm b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/AsmSaveSecContext.asm new file mode 100644 index 0000000000..703b38b52e --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/AsmSaveSecContext.asm @@ -0,0 +1,51 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2014, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; +; SecEntry.asm +; +; Abstract: +; +; This is the code that goes from real-mode to protected mode. +; It consumes the reset vector, calls two basic APIs from FSP binary. +; +;------------------------------------------------------------------------------ + +.686p +.xmm +.model flat,c +.code + +;---------------------------------------------------------------------------- +; MMX Usage: +; MM0 = BIST State +; MM5 = Save time-stamp counter value high32bit +; MM6 = Save time-stamp counter value low32bit. +; +; It should be same as SecEntry.asm and PeiCoreEntry.asm. +;---------------------------------------------------------------------------- + +AsmSaveBistValue PROC PUBLIC + mov eax, [esp+4] + movd mm0, eax + ret +AsmSaveBistValue ENDP + +AsmSaveTickerValue PROC PUBLIC + mov eax, [esp+4] + movd mm6, eax + mov eax, [esp+8] + movd mm5, eax + ret +AsmSaveTickerValue ENDP + +END diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/Fsp.inc b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/Fsp.inc new file mode 100644 index 0000000000..296c47eb1d --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/Fsp.inc @@ -0,0 +1,51 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2014, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; +; Fsp.inc +; +; Abstract: +; +; Fsp related definitions +; +;------------------------------------------------------------------------------ + + +; +; Fv Header +; +FVH_SIGINATURE_OFFSET EQU 028h +FVH_SIGINATURE_VALID_VALUE EQU 04856465Fh ; valid signature:_FVH +FVH_HEADER_LENGTH_OFFSET EQU 030h +FVH_EXTHEADER_OFFSET_OFFSET EQU 034h +FVH_EXTHEADER_SIZE_OFFSET EQU 010h + +; +; Ffs Header +; +FSP_HEADER_GUID_DWORD1 EQU 0912740BEh +FSP_HEADER_GUID_DWORD2 EQU 047342284h +FSP_HEADER_GUID_DWORD3 EQU 0B08471B9h +FSP_HEADER_GUID_DWORD4 EQU 00C3F3527h +FFS_HEADER_SIZE_VALUE EQU 018h + +; +; Section Header +; +SECTION_HEADER_TYPE_OFFSET EQU 03h +RAW_SECTION_HEADER_SIZE_VALUE EQU 04h + +; +; Fsp Header +; +FSP_HEADER_IMAGEBASE_OFFSET EQU 01Ch +FSP_HEADER_TEMPRAMINIT_OFFSET EQU 030h diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/PeiCoreEntry.asm b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/PeiCoreEntry.asm new file mode 100644 index 0000000000..59350344b4 --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/PeiCoreEntry.asm @@ -0,0 +1,141 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2014, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; +; SecEntry.asm +; +; Abstract: +; +; This is the code that goes from real-mode to protected mode. +; It consumes the reset vector, calls two basic APIs from FSP binary. +; +;------------------------------------------------------------------------------ + +.686p +.xmm +.model flat, c +.code + +EXTRN SecStartup:NEAR +EXTRN PlatformInit:NEAR + +CallPeiCoreEntryPoint PROC PUBLIC + ; + ; Obtain the hob list pointer + ; + mov eax, [esp+4] + ; + ; Obtain the stack information + ; ECX: start of range + ; EDX: end of range + ; + mov ecx, [esp+8] + mov edx, [esp+0Ch] + + ; + ; Platform init + ; + pushad + push edx + push ecx + push eax + call PlatformInit + pop eax + pop eax + pop eax + popad + + ; + ; Set stack top pointer + ; + mov esp, edx + + ; + ; Push the hob list pointer + ; + push eax + + ; + ; Save the value + ; ECX: start of range + ; EDX: end of range + ; + mov ebp, esp + push ecx + push edx + + ; + ; 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: + movd eax, mm0 + push eax + loop PushBist + + ; Save Time-Stamp Counter + movd eax, mm5 + push eax + + movd eax, mm6 + push eax + + ; + ; Pass entry point of the PEI core + ; + mov edi, 0FFFFFFE0h + push DWORD PTR ds:[edi] + + ; + ; Pass BFV into the PEI Core + ; + mov edi, 0FFFFFFFCh + push DWORD PTR ds:[edi] + + ; + ; Pass stack size into the PEI Core + ; + mov ecx, [ebp - 4] + mov edx, [ebp - 8] + push ecx ; RamBase + + sub edx, ecx + push edx ; RamSize + + ; + ; Pass Control into the PEI Core + ; + call SecStartup +CallPeiCoreEntryPoint ENDP + +END diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/SecEntry.asm b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/SecEntry.asm new file mode 100644 index 0000000000..f8a318252e --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/SecEntry.asm @@ -0,0 +1,344 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2014, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; +; SecEntry.asm +; +; Abstract: +; +; This is the code that goes from real-mode to protected mode. +; It consumes the reset vector, calls two basic APIs from FSP binary. +; +;------------------------------------------------------------------------------ + INCLUDE Fsp.inc + +.686p +.xmm +.model small, c + +EXTRN CallPeiCoreEntryPoint:NEAR +EXTRN TempRamInitParams:FAR + +; Pcds +EXTRN PcdGet32 (PcdFlashFvFspBase):DWORD +EXTRN PcdGet32 (PcdFlashFvFspSize):DWORD + +_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 +; +; MMX Usage: +; MM0 = BIST State +; MM5 = Save time-stamp counter value high32bit +; MM6 = Save time-stamp counter value low32bit. +; +;---------------------------------------------------------------------------- + +align 4 +_ModuleEntryPoint PROC NEAR C PUBLIC + fninit ; clear any pending Floating point exceptions + ; + ; Store the BIST value in mm0 + ; + movd mm0, eax + + ; + ; Save time-stamp counter value + ; rdtsc load 64bit time-stamp counter to EDX:EAX + ; + rdtsc + movd mm5, edx + movd mm6, eax + + ; + ; 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 + + mov eax, cr4 ; Get control register 4 + or eax, 00000600h ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10) + mov cr4, eax + + ; + ; Now we're in 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 + +_TEXT_PROTECTED_MODE SEGMENT PARA PUBLIC USE32 'CODE' + ASSUME CS:_TEXT_PROTECTED_MODE, DS:_TEXT_PROTECTED_MODE + +;---------------------------------------------------------------------------- +; +; Procedure: ProtectedModeEntryPoint +; +; Input: None +; +; Output: None +; +; Destroys: Assume all registers +; +; Description: +; +; This function handles: +; Call two basic APIs from FSP binary +; Initializes stack with some early data (BIST, PEI entry, etc) +; +; Return: None +; +;---------------------------------------------------------------------------- + +align 4 +ProtectedModeEntryPoint PROC NEAR PUBLIC + + ; Find the fsp info header + mov edi, PcdGet32 (PcdFlashFvFspBase) + mov ecx, PcdGet32 (PcdFlashFvFspSize) + + mov eax, dword ptr [edi + FVH_SIGINATURE_OFFSET] + cmp eax, FVH_SIGINATURE_VALID_VALUE + jnz FspHeaderNotFound + + xor eax, eax + mov ax, word ptr [edi + FVH_EXTHEADER_OFFSET_OFFSET] + cmp ax, 0 + jnz FspFvExtHeaderExist + + xor eax, eax + mov ax, word ptr [edi + FVH_HEADER_LENGTH_OFFSET] ; Bypass Fv Header + add edi, eax + jmp FspCheckFfsHeader + +FspFvExtHeaderExist: + add edi, eax + mov eax, dword ptr [edi + FVH_EXTHEADER_SIZE_OFFSET] ; Bypass Ext Fv Header + add edi, eax + + ; Round up to 8 byte alignment + mov eax, edi + and al, 07h + jz FspCheckFfsHeader + + and edi, 0FFFFFFF8h + add edi, 08h + +FspCheckFfsHeader: + ; Check the ffs guid + mov eax, dword ptr [edi] + cmp eax, FSP_HEADER_GUID_DWORD1 + jnz FspHeaderNotFound + + mov eax, dword ptr [edi + 4] + cmp eax, FSP_HEADER_GUID_DWORD2 + jnz FspHeaderNotFound + + mov eax, dword ptr [edi + 8] + cmp eax, FSP_HEADER_GUID_DWORD3 + jnz FspHeaderNotFound + + mov eax, dword ptr [edi + 0Ch] + cmp eax, FSP_HEADER_GUID_DWORD4 + jnz FspHeaderNotFound + + add edi, FFS_HEADER_SIZE_VALUE ; Bypass the ffs header + + ; Check the section type as raw section + mov al, byte ptr [edi + SECTION_HEADER_TYPE_OFFSET] + cmp al, 019h + jnz FspHeaderNotFound + + add edi, RAW_SECTION_HEADER_SIZE_VALUE ; Bypass the section header + jmp FspHeaderFound + +FspHeaderNotFound: + jmp $ + +FspHeaderFound: + ; Get the fsp TempRamInit Api address + mov eax, dword ptr [edi + FSP_HEADER_IMAGEBASE_OFFSET] + add eax, dword ptr [edi + FSP_HEADER_TEMPRAMINIT_OFFSET] + + ; Setup the hardcode stack + mov esp, OFFSET TempRamInitStack + + ; Call the fsp TempRamInit Api + jmp eax + +TempRamInitDone: + cmp eax, 0 + jnz FspApiFailed + + ; ECX: start of range + ; EDX: end of range + mov esp, edx + push edx + push ecx + push eax ; zero - no hob list yet + call CallPeiCoreEntryPoint + +FspApiFailed: + jmp $ + +align 10h +TempRamInitStack: + DD OFFSET TempRamInitDone + DD OFFSET TempRamInitParams + +ProtectedModeEntryPoint 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 data segment descriptor +; +LINEAR_SEL EQU $ - GDT_BASE ; Selector [0x8] + DW 0FFFFh ; limit 0xFFFFF + DW 0 ; base 0 + DB 0 + DB 092h ; present, ring 0, data, expand-up, writable + DB 0CFh ; page-granular, 32-bit + DB 0 +; +; Linear code segment descriptor +; +LINEAR_CODE_SEL EQU $ - GDT_BASE ; Selector [0x10] + DW 0FFFFh ; limit 0xFFFFF + DW 0 ; base 0 + DB 0 + DB 09Bh ; present, ring 0, data, expand-up, not-writable + DB 0CFh ; page-granular, 32-bit + DB 0 +; +; System data segment descriptor +; +SYS_DATA_SEL EQU $ - GDT_BASE ; Selector [0x18] + DW 0FFFFh ; limit 0xFFFFF + DW 0 ; base 0 + DB 0 + DB 093h ; present, ring 0, data, expand-up, not-writable + DB 0CFh ; page-granular, 32-bit + DB 0 + +; +; System code segment descriptor +; +SYS_CODE_SEL EQU $ - GDT_BASE ; Selector [0x20] + DW 0FFFFh ; limit 0xFFFFF + DW 0 ; base 0 + DB 0 + DB 09Ah ; present, ring 0, data, expand-up, writable + DB 0CFh ; page-granular, 32-bit + DB 0 +; +; Spare segment descriptor +; +SYS16_CODE_SEL EQU $ - GDT_BASE ; Selector [0x28] + DW 0FFFFh ; limit 0xFFFFF + DW 0 ; base 0 + DB 0Eh ; Changed from F000 to E000. + DB 09Bh ; present, ring 0, code, expand-up, writable + DB 00h ; byte-granular, 16-bit + DB 0 +; +; Spare segment descriptor +; +SYS16_DATA_SEL EQU $ - GDT_BASE ; Selector [0x30] + DW 0FFFFh ; limit 0xFFFF + DW 0 ; base 0 + DB 0 + DB 093h ; present, ring 0, data, expand-up, not-writable + DB 00h ; byte-granular, 16-bit + DB 0 + +; +; Spare segment descriptor +; +SPARE5_SEL EQU $ - GDT_BASE ; Selector [0x38] + DW 0 ; limit 0 + DW 0 ; base 0 + DB 0 + DB 0 ; present, ring 0, data, expand-up, writable + DB 0 ; page-granular, 32-bit + DB 0 +GDT_SIZE EQU $ - BootGdtTable ; Size, in bytes + +; +; 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 + +_TEXT_PROTECTED_MODE ENDS +END diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/Stack.S b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/Stack.S new file mode 100644 index 0000000000..950b3a1f0a --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/Stack.S @@ -0,0 +1,77 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# 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/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/Stack.asm b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/Stack.asm new file mode 100644 index 0000000000..f96a55f040 --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/Ia32/Stack.asm @@ -0,0 +1,82 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2014, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/PlatformInit.c b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/PlatformInit.c new file mode 100644 index 0000000000..2e181ac5e0 --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/PlatformInit.c @@ -0,0 +1,42 @@ +/** @file + This PEIM will parse the hoblist from fsp and report them into pei core. + This file contains the main entrypoint of the PEIM. + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include +#include +#include + +VOID EnableInternalUart (); + +VOID +EFIAPI +PlatformInit ( + IN VOID *FspHobList, + IN VOID *StartOfRange, + IN VOID *EndOfRange + ) +{ + // + // Platform initialization + // Enable Serial port here + // + EnableInternalUart (); + SerialPortInitialize (); + + DEBUG ((DEBUG_INFO, "PlatformInit\n")); + DEBUG ((DEBUG_INFO, "FspHobList - 0x%x\n", FspHobList)); + DEBUG ((DEBUG_INFO, "StartOfRange - 0x%x\n", StartOfRange)); + DEBUG ((DEBUG_INFO, "EndOfRange - 0x%x\n", EndOfRange)); +} diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SaveSecContext.c b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SaveSecContext.c new file mode 100644 index 0000000000..6f84f505c0 --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SaveSecContext.c @@ -0,0 +1,114 @@ +/** @file + This PEIM will parse the hoblist from fsp and report them into pei core. + This file contains the main entrypoint of the PEIM. + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include +#include + +#include +#include + +/** + Save BIST value before call FspInit. + + @param Bist BIST value. +**/ +VOID +AsmSaveBistValue ( + IN UINT32 Bist + ); + +/** + Save Ticker value before call FspInit. + + @param Ticker Ticker value. +**/ +VOID +AsmSaveTickerValue ( + IN UINT64 Ticker + ); + +/** + Save SEC context before call FspInit. + + @param PeiServices Pointer to PEI Services Table. +**/ +VOID +EFIAPI +SaveSecContext ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + UINT32 *Bist; + UINT64 *Ticker; + UINT32 Size; + UINT32 Count; + UINT32 TopOfTemporaryRam; + VOID *TopOfTemporaryRamPpi; + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "SaveSecContext - 0x%x\n", PeiServices)); + + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gTopOfTemporaryRamPpiGuid, + 0, + NULL, + (VOID **) &TopOfTemporaryRamPpi + ); + if (EFI_ERROR (Status)) { + return ; + } + + DEBUG ((DEBUG_INFO, "TopOfTemporaryRamPpi - 0x%x\n", TopOfTemporaryRamPpi)); + + // + // 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. + // + // |--------------| <- TopOfTemporaryRam + // |Number of BSPs| + // |--------------| + // | BIST | + // |--------------| + // | .... | + // |--------------| + // | TSC[63:32] | + // |--------------| + // | TSC[31:00] | + // |--------------| + // + + TopOfTemporaryRam = (UINT32)(UINTN)TopOfTemporaryRamPpi - sizeof(UINT32); + TopOfTemporaryRam -= sizeof(UINT32) * 2; + DEBUG ((DEBUG_INFO, "TopOfTemporaryRam - 0x%x\n", TopOfTemporaryRam)); + Count = *(UINT32 *)(UINTN)(TopOfTemporaryRam - sizeof(UINT32)); + DEBUG ((DEBUG_INFO, "Count - 0x%x\n", Count)); + Size = Count * sizeof (IA32_HANDOFF_STATUS); + DEBUG ((DEBUG_INFO, "Size - 0x%x\n", Size)); + + Bist = (UINT32 *)(UINTN)(TopOfTemporaryRam - sizeof(UINT32) - Size); + DEBUG ((DEBUG_INFO, "Bist - 0x%x\n", *Bist)); + Ticker = (UINT64 *)(UINTN)(TopOfTemporaryRam - sizeof(UINT32) - Size - sizeof(UINT64)); + DEBUG ((DEBUG_INFO, "Ticker - 0x%lx\n", *Ticker)); + + // + // Just need record BSP + // + AsmSaveBistValue (*Bist); + AsmSaveTickerValue (*Ticker); +} diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecGetPerformance.c b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecGetPerformance.c new file mode 100644 index 0000000000..ce7a9594c2 --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecGetPerformance.c @@ -0,0 +1,89 @@ +/** @file + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include + +#include +#include +#include + +/** + This interface conveys performance information out of the Security (SEC) phase into PEI. + + This service is published by the SEC phase. The SEC phase handoff has an optional + EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the + PEI Foundation. As such, if the platform supports collecting performance data in SEC, + this information is encapsulated into the data structure abstracted by this service. + This information is collected for the boot-strap processor (BSP) on IA-32. + + @param[in] PeiServices The pointer to the PEI Services Table. + @param[in] This The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI. + @param[out] Performance The pointer to performance data collected in SEC phase. + + @retval EFI_SUCCESS The data was successfully returned. + +**/ +EFI_STATUS +EFIAPI +SecGetPerformance ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN PEI_SEC_PERFORMANCE_PPI *This, + OUT FIRMWARE_SEC_PERFORMANCE *Performance + ) +{ + UINT32 Size; + UINT32 Count; + UINT32 TopOfTemporaryRam; + UINT64 Ticker; + VOID *TopOfTemporaryRamPpi; + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "SecGetPerformance\n")); + + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gTopOfTemporaryRamPpiGuid, + 0, + NULL, + (VOID **) &TopOfTemporaryRamPpi + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // |--------------| <- TopOfTemporaryRam + // |Number of BSPs| + // |--------------| + // | BIST | + // |--------------| + // | .... | + // |--------------| + // | TSC[63:32] | + // |--------------| + // | TSC[31:00] | + // |--------------| + // + TopOfTemporaryRam = (UINT32)(UINTN)TopOfTemporaryRamPpi - sizeof(UINT32); + TopOfTemporaryRam -= sizeof(UINT32) * 2; + Count = *(UINT32 *) (UINTN) (TopOfTemporaryRam - sizeof (UINT32)); + Size = Count * sizeof (UINT64); + + Ticker = *(UINT64 *) (UINTN) (TopOfTemporaryRam - sizeof (UINT32) - Size - sizeof (UINT32) * 2); + Performance->ResetEnd = GetTimeInNanoSecond (Ticker); + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecPlatformInformation.c b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecPlatformInformation.c new file mode 100644 index 0000000000..50e5cb2670 --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecPlatformInformation.c @@ -0,0 +1,83 @@ +/** @file + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and + made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include + +#include +#include + +/** + 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; + UINT32 TopOfTemporaryRam; + VOID *TopOfTemporaryRamPpi; + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "SecPlatformInformation\n")); + + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gTopOfTemporaryRamPpiGuid, + 0, + NULL, + (VOID **) &TopOfTemporaryRamPpi + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // 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. + // + TopOfTemporaryRam = (UINT32)(UINTN)TopOfTemporaryRamPpi - sizeof (UINT32); + TopOfTemporaryRam -= sizeof(UINT32) * 2; + Count = *((UINT32 *)(UINTN) (TopOfTemporaryRam - sizeof (UINT32))); + Size = Count * sizeof (IA32_HANDOFF_STATUS); + + if ((*StructureSize) < (UINT64) Size) { + *StructureSize = Size; + return EFI_BUFFER_TOO_SMALL; + } + + *StructureSize = Size; + Bist = (UINT32 *) (TopOfTemporaryRam - sizeof (UINT32) - Size); + + CopyMem (PlatformInformationRecord, Bist, Size); + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecRamInitData.c b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecRamInitData.c new file mode 100644 index 0000000000..392bd2132d --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecRamInitData.c @@ -0,0 +1,22 @@ +/** @file + Calling Fsp Apis in SEC + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made + available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 TempRamInitParams[4] = { + ((UINT32)FixedPcdGet64 (PcdCpuMicrocodePatchAddress) + FixedPcdGet32 (PcdFlashMicroCodeOffset)), + ((UINT32)FixedPcdGet64 (PcdCpuMicrocodePatchRegionSize) - FixedPcdGet32 (PcdFlashMicroCodeOffset)), + FixedPcdGet32 (PcdFlashCodeCacheAddress), + FixedPcdGet32 (PcdFlashCodeCacheSize) +}; diff --git a/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecTempRamSupport.c b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecTempRamSupport.c new file mode 100644 index 0000000000..e505d719c2 --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/SecTempRamSupport.c @@ -0,0 +1,155 @@ +/** @file + C functions in SEC + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made + available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include + +#include +#include +#include +#include + +/** + 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 + ) +{ + 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/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/UartInit.c b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/UartInit.c new file mode 100644 index 0000000000..4255ad3712 --- /dev/null +++ b/Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/UartInit.c @@ -0,0 +1,198 @@ +/** @file + This PEIM will parse the hoblist from fsp and report them into pei core. + This file contains the main entrypoint of the PEIM. + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include +#include +#include + +#define PCI_IDX 0xCF8 +#define PCI_DAT 0xCFC + +#define PCI_LPC_BASE (0x8000F800) +#define PCI_LPC_REG(x) (PCI_LPC_BASE + (x)) + +#define PMC_BASE_ADDRESS 0xFED03000 // PMC Memory Base Address +#define R_PCH_LPC_PMC_BASE 0x44 // PBASE, 32bit, 512 Bytes +#define B_PCH_LPC_PMC_BASE_EN BIT1 // Enable Bit +#define R_PCH_PMC_GEN_PMCON_1 0x20 // General PM Configuration 1 +#define B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR BIT14 // SUS Well Power Failure +#define B_PCH_PMC_GEN_PMCON_PWROK_FLR BIT16 // PWROK Failure + +#define R_PCH_LPC_UART_CTRL 0x80 // UART Control +#define B_PCH_LPC_UART_CTRL_COM1_EN BIT0 // COM1 Enable + +#define ILB_BASE_ADDRESS 0xFED08000 // ILB Memory Base Address +#define R_PCH_ILB_IRQE 0x88 // IRQ Enable Control + +#define IO_BASE_ADDRESS 0xFED0C000 // IO Memory Base Address + +#define V_PCH_ILB_IRQE_UARTIRQEN_IRQ3 BIT3 // UART IRQ3 Enable +#define V_PCH_ILB_IRQE_UARTIRQEN_IRQ4 BIT4 // UART IRQ4 Enable +#define PCIEX_BASE_ADDRESS 0xE0000000 +#define PCI_EXPRESS_BASE_ADDRESS PCIEX_BASE_ADDRESS +#define PciD31F0RegBase PCIEX_BASE_ADDRESS + (UINT32) (31 << 15) +#define SB_RCBA 0xfed1c000 + +typedef enum { + PchA0 = 0, + PchA1 = 1, + PchB0 = 2, + PchB1 = 3, + PchB2 = 4, + PchB3 = 5, + PchC0 = 6, + PchSteppingMax +} PCH_STEPPING; + +#define MmPciAddress( Segment, Bus, Device, Function, Register ) \ + ( (UINTN)PCI_EXPRESS_BASE_ADDRESS + \ + (UINTN)(Bus << 20) + \ + (UINTN)(Device << 15) + \ + (UINTN)(Function << 12) + \ + (UINTN)(Register) \ + ) + +#define DEFAULT_PCI_BUS_NUMBER_PCH 0 +#define PCI_DEVICE_NUMBER_PCH_LPC 31 +#define PCI_FUNCTION_NUMBER_PCH_LPC 0 + +#define R_PCH_LPC_RID_CC 0x08 // Revision ID & Class Code + +#define V_PCH_LPC_RID_0 0x01 // A0 Stepping (17 x 17) +#define V_PCH_LPC_RID_1 0x02 // A0 Stepping (25 x 27) +#define V_PCH_LPC_RID_2 0x03 // A1 Stepping (17 x 17) +#define V_PCH_LPC_RID_3 0x04 // A1 Stepping (25 x 27) +#define V_PCH_LPC_RID_4 0x05 // B0 Stepping (17 x 17) +#define V_PCH_LPC_RID_5 0x06 // B0 Stepping (25 x 27) +#define V_PCH_LPC_RID_6 0x07 // B1 Stepping (17 x 17) +#define V_PCH_LPC_RID_7 0x08 // B1 Stepping (25 x 27) +#define V_PCH_LPC_RID_8 0x09 // B2 Stepping (17 x 17) +#define V_PCH_LPC_RID_9 0x0A // B2 Stepping (25 x 27) +#define V_PCH_LPC_RID_A 0x0B // B3 Stepping (17 x 17) +#define V_PCH_LPC_RID_B 0x0C // B3 Stepping (25 x 27) +#define V_PCH_LPC_RID_C 0x0D // C0 Stepping (17 x 17) +#define V_PCH_LPC_RID_D 0x0E // C0 Stepping (25 x 27) + +/** + Return Pch stepping type + + @param[in] None + + @retval PCH_STEPPING Pch stepping type + +**/ +PCH_STEPPING +EFIAPI +PchStepping ( + VOID + ) +{ + UINT8 RevId; + + RevId = MmioRead8 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_RID_CC) + ); + + switch (RevId) { + case V_PCH_LPC_RID_0: + case V_PCH_LPC_RID_1: + return PchA0; + break; + + case V_PCH_LPC_RID_2: + case V_PCH_LPC_RID_3: + return PchA1; + break; + + case V_PCH_LPC_RID_4: + case V_PCH_LPC_RID_5: + return PchB0; + break; + + case V_PCH_LPC_RID_6: + case V_PCH_LPC_RID_7: + return PchB1; + break; + + case V_PCH_LPC_RID_8: + case V_PCH_LPC_RID_9: + return PchB2; + break; + + case V_PCH_LPC_RID_A: + case V_PCH_LPC_RID_B: + return PchB3; + break; + + case V_PCH_LPC_RID_C: + case V_PCH_LPC_RID_D: + return PchC0; + break; + + default: + return PchSteppingMax; + break; + + } +} + +/** + Enable legacy decoding on ICH6 + + @param[in] none + + @retval EFI_SUCCESS Always returns success. + +**/ +VOID +EnableInternalUart( + VOID + ) +{ + + // + // Program and enable PMC Base. + // + IoWrite32 (PCI_IDX, PCI_LPC_REG(R_PCH_LPC_PMC_BASE)); + IoWrite32 (PCI_DAT, (PMC_BASE_ADDRESS | B_PCH_LPC_PMC_BASE_EN)); + + // + // Enable COM1 for debug message output. + // + MmioAndThenOr32 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, (UINT32) (~(B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR + B_PCH_PMC_GEN_PMCON_PWROK_FLR)), BIT24); + + // + // Silicon Steppings + // + if (PchStepping()>= PchB0) + MmioOr8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) V_PCH_ILB_IRQE_UARTIRQEN_IRQ4); + else + MmioOr8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) V_PCH_ILB_IRQE_UARTIRQEN_IRQ3); + MmioAnd32(IO_BASE_ADDRESS + 0x0520, (UINT32)~(0x00000187)); + MmioOr32 (IO_BASE_ADDRESS + 0x0520, (UINT32)0x81); // UART3_RXD-L + MmioAnd32(IO_BASE_ADDRESS + 0x0530, (UINT32)~(0x00000007)); + MmioOr32 (IO_BASE_ADDRESS + 0x0530, (UINT32)0x1); // UART3_RXD-L + MmioOr8 (PciD31F0RegBase + R_PCH_LPC_UART_CTRL, (UINT8) B_PCH_LPC_UART_CTRL_COM1_EN); + + SerialPortInitialize (); + SerialPortWrite ("EnableInternalUart!\r\n", sizeof("EnableInternalUart!\r\n") - 1); + + return ; +} diff --git a/Vlv2TbltDevicePkg/FvInfoPei/FvInfoPei.c b/Vlv2TbltDevicePkg/FvInfoPei/FvInfoPei.c new file mode 100644 index 0000000000..5d8aa8065d --- /dev/null +++ b/Vlv2TbltDevicePkg/FvInfoPei/FvInfoPei.c @@ -0,0 +1,73 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + FvInfoPei.c + +Abstract: + + EFI 2.0 PEIM to initialize the cache and program for unlock processor + + + +--*/ + +#include +#include +#include +#include +#include + +EFI_PEI_FIRMWARE_VOLUME_INFO_PPI mAddtionFVPpi = { + EFI_FIRMWARE_FILE_SYSTEM2_GUID, + (VOID*)(UINTN)FixedPcdGet32(PcdFlashFvRecovery2Base), + FixedPcdGet32(PcdFlashFvRecovery2Size), + NULL, + NULL +}; + +EFI_PEI_PPI_DESCRIPTOR mPpiList[] = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiFirmwareVolumeInfoPpiGuid, + &mAddtionFVPpi +}; + + +/** + Add Recovery Fv Info to the Pei Core. + + @param PeiServices General purpose services available to every PEIM. + + @retval Status + +**/ +EFI_STATUS +EFIAPI +PeimInitializeFvInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) + +// +// GC_TODO: FfsHeader - add argument and description to function comment +// +{ + EFI_STATUS Status; + Status = (**PeiServices).InstallPpi (PeiServices, &mPpiList[0]); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "\nFvInfo Add Fv Info\n")); + + return Status; +} diff --git a/Vlv2TbltDevicePkg/FvInfoPei/FvInfoPei.inf b/Vlv2TbltDevicePkg/FvInfoPei/FvInfoPei.inf new file mode 100644 index 0000000000..bf0cc3cb31 --- /dev/null +++ b/Vlv2TbltDevicePkg/FvInfoPei/FvInfoPei.inf @@ -0,0 +1,54 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# Module Name: +# +# CpuPeim.inf +# +# Abstract: +# +# Component description file for CPU module +# +# +#--*/ + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = FvInfoPei + FILE_GUID = 64AAEAE0-92DF-4980-8668-6EB5EAAF4393 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = PeimInitializeFvInfo + +[sources.common] + FvInfoPei.c + +[Packages] + MdePkg/MdePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + +[LibraryClasses] + PeimEntryPoint + DebugLib + +[Pcd.common] + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Base + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Size + +[Ppis] + gEfiPeiFirmwareVolumeInfoPpiGuid + +[Depex] + TRUE + diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbInfo.c b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbInfo.c new file mode 100644 index 0000000000..832e246d1c --- /dev/null +++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbInfo.c @@ -0,0 +1,175 @@ +/**@file + Defines data structure that is the volume header found. + These data is intent to decouple FVB driver with FV header. + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include +#include +#include +#include +#include +#include +#include + +#define FIRMWARE_BLOCK_SIZE 0x8000 +#define FVB_MEDIA_BLOCK_SIZE (FIRMWARE_BLOCK_SIZE * 2) + +#define FV_RECOVERY_BASE_ADDRESS FixedPcdGet32(PcdFlashFvRecoveryBase) +#define RECOVERY_BIOS_BLOCK_NUM (FixedPcdGet32(PcdFlashFvRecoverySize) / FVB_MEDIA_BLOCK_SIZE) + +#define FV_MAIN_BASE_ADDRESS FixedPcdGet32(PcdFlashFvMainBase) +#define MAIN_BIOS_BLOCK_NUM (FixedPcdGet32(PcdFlashFvMainSize) / FVB_MEDIA_BLOCK_SIZE) + +#define NV_STORAGE_BASE_ADDRESS FixedPcdGet32(PcdFlashNvStorageVariableBase) +#define SYSTEM_NV_BLOCK_NUM ((FixedPcdGet32(PcdFlashNvStorageVariableSize)+ FixedPcdGet32(PcdFlashNvStorageFtwWorkingSize) + FixedPcdGet32(PcdFlashNvStorageFtwSpareSize))/ FVB_MEDIA_BLOCK_SIZE) + +typedef struct { + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_FIRMWARE_VOLUME_HEADER FvbInfo; + EFI_FV_BLOCK_MAP_ENTRY End[1]; +} EFI_FVB2_MEDIA_INFO; + +// +// This data structure contains a template of all correct FV headers, which is used to restore +// Fv header if it's corrupted. +// +EFI_FVB2_MEDIA_INFO mPlatformFvbMediaInfo[] = { + // + // Main BIOS FVB + // + { + FV_MAIN_BASE_ADDRESS, + { + {0,}, //ZeroVector[16] + EFI_FIRMWARE_FILE_SYSTEM2_GUID, + FVB_MEDIA_BLOCK_SIZE * MAIN_BIOS_BLOCK_NUM, + EFI_FVH_SIGNATURE, + 0x0004feff, // check MdePkg/Include/Pi/PiFirmwareVolume.h for details on EFI_FVB_ATTRIBUTES_2 + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY), + 0, //CheckSum which will be calucated dynamically. + 0, //ExtHeaderOffset + {0,}, //Reserved[1] + 2, //Revision + { + { + MAIN_BIOS_BLOCK_NUM, + FVB_MEDIA_BLOCK_SIZE, + } + } + }, + { + { + 0, + 0 + } + } + }, + + // + // Systen NvStorage FVB + // + { + NV_STORAGE_BASE_ADDRESS, + { + {0,}, //ZeroVector[16] + EFI_SYSTEM_NV_DATA_FV_GUID, + FVB_MEDIA_BLOCK_SIZE * SYSTEM_NV_BLOCK_NUM, + EFI_FVH_SIGNATURE, + 0x0004feff, // check MdePkg/Include/Pi/PiFirmwareVolume.h for details on EFI_FVB_ATTRIBUTES_2 + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY), + 0, //CheckSum which will be calucated dynamically. + 0, //ExtHeaderOffset + {0,}, //Reserved[1] + 2, //Revision + { + { + SYSTEM_NV_BLOCK_NUM, + FVB_MEDIA_BLOCK_SIZE, + } + } + }, + { + { + 0, + 0 + } + } + }, + + // + // Recovery BIOS FVB + // + { + FV_RECOVERY_BASE_ADDRESS, + { + {0,}, //ZeroVector[16] + EFI_FIRMWARE_FILE_SYSTEM2_GUID, + FVB_MEDIA_BLOCK_SIZE * RECOVERY_BIOS_BLOCK_NUM, + EFI_FVH_SIGNATURE, + 0x0004feff, // check MdePkg/Include/Pi/PiFirmwareVolume.h for details on EFI_FVB_ATTRIBUTES_2 + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY), + 0, //CheckSum which will be calucated dynamically. + 0, //ExtHeaderOffset + {0,}, //Reserved[1] + 2, //Revision + { + { + RECOVERY_BIOS_BLOCK_NUM, + FVB_MEDIA_BLOCK_SIZE, + } + } + }, + { + { + 0, + 0 + } + } + } +}; + +EFI_STATUS +GetFvbInfo ( + IN EFI_PHYSICAL_ADDRESS FvBaseAddress, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ) +{ + UINTN Index; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + + for (Index = 0; Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB2_MEDIA_INFO); Index += 1) { + if (mPlatformFvbMediaInfo[Index].BaseAddress == FvBaseAddress) { + FvHeader = &mPlatformFvbMediaInfo[Index].FvbInfo; + + // + // Update the checksum value of FV header. + // + FvHeader->Checksum = CalculateCheckSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + + *FvbInfo = FvHeader; + + DEBUG ((EFI_D_INFO, "\nBaseAddr: 0x%lx \n", FvBaseAddress)); + DEBUG ((EFI_D_INFO, "FvLength: 0x%lx \n", (*FvbInfo)->FvLength)); + DEBUG ((EFI_D_INFO, "HeaderLength: 0x%x \n", (*FvbInfo)->HeaderLength)); + DEBUG ((EFI_D_INFO, "FvBlockMap[0].NumBlocks: 0x%x \n", (*FvbInfo)->BlockMap[0].NumBlocks)); + DEBUG ((EFI_D_INFO, "FvBlockMap[0].BlockLength: 0x%x \n", (*FvbInfo)->BlockMap[0].Length)); + DEBUG ((EFI_D_INFO, "FvBlockMap[1].NumBlocks: 0x%x \n", (*FvbInfo)->BlockMap[1].NumBlocks)); + DEBUG ((EFI_D_INFO, "FvBlockMap[1].BlockLength: 0x%x \n\n", (*FvbInfo)->BlockMap[1].Length)); + + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbRuntimeDxe.inf b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbRuntimeDxe.inf new file mode 100644 index 0000000000..e8e6411fe4 --- /dev/null +++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbRuntimeDxe.inf @@ -0,0 +1,85 @@ +## @file +# This driver implement the EFI_FIRMWARE_VOLUMEN_PROTOCOL. +# +# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FvbRuntimeDxe + FILE_GUID = FD3B7E55-FA7B-4e07-AE1D-208B81FB0BAD + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DxeFvbInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# +# VIRTUAL_ADDRESS_MAP_CALLBACK = FvbVirtualddressChangeEvent +# + +[Sources] + FvbInfo.c + FvbService.h + FvbService.c + FvbServiceDxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + +[LibraryClasses] + FlashDeviceLib + PcdLib + MemoryAllocationLib + CacheMaintenanceLib + IoLib + BaseMemoryLib + DebugLib + BaseLib + UefiLib + UefiRuntimeLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Guids] + gEfiFirmwareFileSystem2Guid # ALWAYS_CONSUMED + gEfiSystemNvDataFvGuid # ALWAYS_CONSUMED + gEfiEventVirtualAddressChangeGuid + +[Protocols] + gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL ALWAYS_PRODUCED + +[FixedPcd] + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoveryBase + +[Pcd] + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainSize + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoverySize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + + +[Depex] + gEfiSpiProtocolGuid AND gEfiRuntimeArchProtocolGuid + diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.c b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.c new file mode 100644 index 0000000000..da7dce6e13 --- /dev/null +++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.c @@ -0,0 +1,1114 @@ +/** @file + Firmware Volume Block Driver for Lakeport Platform. + + Firmware volume block driver for FWH or SPI device. + It depends on which Flash Device Library to be linked with this driver. + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include "FvbService.h" + +// +// Global variable for this FVB driver which contains +// the private data of all firmware volume block instances. +// +FWB_GLOBAL mFvbModuleGlobal; + +// +// This platform driver knows there are 3 FVs on +// FD, which are FvRecovery, FvMain and FvNvStorage. +// +UINT32 mPlatformFvBaseAddress[] = { + FixedPcdGet32(PcdFlashNvStorageVariableBase), +}; + +FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = { + { + { + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + { + (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), + (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) + } + }, + EfiMemoryMappedIO, + (EFI_PHYSICAL_ADDRESS) 0, + (EFI_PHYSICAL_ADDRESS) 0, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = { + { + { + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_VOL_DP, + { + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)), + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8) + } + }, + { 0 } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +// +// Template structure used when installing FVB protocol. +// +EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = { + FVB_DEVICE_SIGNATURE, + NULL, + 0, // Instance + { + FvbProtocolGetAttributes, + FvbProtocolSetAttributes, + FvbProtocolGetPhysicalAddress, + FvbProtocolGetBlockSize, + FvbProtocolRead, + FvbProtocolWrite, + FvbProtocolEraseBlocks, + NULL + } // FwVolBlockInstance +}; + + +/** + Get the pointer to EFI_FW_VOL_INSTANCE from the buffer pointed + by mFvbModuleGlobal.FvInstance based on a index. + Each EFI_FW_VOL_INSTANCE is with variable length as + we have a block map at the end of the EFI_FIRMWARE_VOLUME_HEADER. + + @param[in] Instance The index of the EFI_FW_VOL_INSTANCE. + + @return A pointer to EFI_FW_VOL_INSTANCE. + +**/ +EFI_FW_VOL_INSTANCE * +GetFvbInstance ( + IN UINTN Instance + ) +{ + EFI_FW_VOL_INSTANCE *FwhRecord; + + if ( Instance >= mFvbModuleGlobal.NumFv ) { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return NULL; + } + + // + // Find the right instance of the FVB private data. + // + FwhRecord = mFvbModuleGlobal.FvInstance; + 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 --; + } + + return FwhRecord; + +} + + +/** + Get the EFI_FVB_ATTRIBUTES_2 of a FV. + + @param[in] The index of the EFI_FW_VOL_INSTANCE. + + @return EFI_FVB_ATTRIBUTES_2 of the FV identified by Instance. + +**/ +STATIC +EFI_FVB_ATTRIBUTES_2 +FvbGetVolumeAttributes ( + IN UINTN Instance + ) +{ + EFI_FW_VOL_INSTANCE * FwInstance = NULL; + FwInstance = GetFvbInstance(Instance); + ASSERT_EFI_ERROR (FwInstance != NULL); + + if ( FwInstance != NULL ) { + return FwInstance->VolumeHeader.Attributes; + } else { + return 0; + } +} + + +/** + Retrieves the starting address of an LBA in an FV. It also + return a few other attribut of the FV. + + @param[in] Instance The index of the EFI_FW_VOL_INSTANCE. + @param[in] Lba The logical block address. + @param[out] LbaAddress On output, contains the physical starting address + of the Lba. + @param[out] LbaLength On output, contains the length of the block. + @param[out] 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. + + @retval EFI_SUCCESS Successfully returns. + @retval EFI_INVALID_PARAMETER Instance not found. + +**/ +STATIC +EFI_STATUS +FvbGetLbaAddress ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *LbaAddress, + OUT UINTN *LbaLength, + OUT UINTN *NumOfBlocks + ) +{ + UINT32 NumBlocks = 0; + UINT32 BlockLength = 0; + UINTN Offset; + EFI_LBA StartLba; + EFI_LBA NextLba; + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap = NULL; + + // + // Find the right instance of the FVB private data. + // + FwhInstance = GetFvbInstance (Instance); + + StartLba = 0; + Offset = 0; + BlockMap = &(FwhInstance->VolumeHeader.BlockMap[0]); + ASSERT_EFI_ERROR (BlockMap != NULL); + + // + // Parse the blockmap of the FV to find which map entry the Lba belongs to. + // + while (TRUE) { + if ( BlockMap != NULL) { + 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 && FwhInstance ) { + *LbaAddress = FwhInstance->FvBase + Offset; + } + + if (LbaLength ) { + *LbaLength = BlockLength; + } + + if (NumOfBlocks ) { + *NumOfBlocks = (UINTN)(NextLba - Lba); + } + return EFI_SUCCESS; + } + + StartLba = NextLba; + Offset = Offset + NumBlocks * BlockLength; + BlockMap++; + } +} + + +/** + Reads specified number of bytes into a buffer from the specified block. + + @param[in] Instance The FV instance to be read from. + @param[in] Lba The logical block address to be read from. + @param[in] BlockOffset Offset into the block at which to begin reading. + @param[in] NumBytes Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes read. + @param[in] Buffer Pointer to a caller allocated buffer that will be + used to hold the data read. + + + @retval EFI_SUCCESS The firmware volume was read successfully and + contents are in Buffer. + @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes returned + in Buffer. + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state. + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and + could not be read. + @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer are NULL. + +**/ +STATIC +EFI_STATUS +FvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_FVB_ATTRIBUTES_2 Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + + if ( (NumBytes == NULL) || (Buffer == NULL)) { + return (EFI_INVALID_PARAMETER); + } + if (*NumBytes == 0) { + return (EFI_INVALID_PARAMETER); + } + + Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL); + if (EFI_ERROR(Status)) { + return Status; + } + + Attributes = FvbGetVolumeAttributes (Instance); + + if ( (Attributes & EFI_FVB2_READ_STATUS) == 0) { + return (EFI_ACCESS_DENIED); + } + + if (BlockOffset > LbaLength) { + return (EFI_INVALID_PARAMETER); + } + + if (LbaLength < ( *NumBytes + BlockOffset ) ) { + *NumBytes = (UINT32) (LbaLength - BlockOffset); + Status = EFI_BAD_BUFFER_SIZE; + } + + LibFvbFlashDeviceRead (LbaAddress + BlockOffset, NumBytes, Buffer); + + return Status; +} + + +/** + Writes specified number of bytes from the input buffer to the block. + + @param[in] Instance The FV instance to be written to. + @param[in] Lba The starting logical block index to write to. + @param[in] BlockOffset Offset into the block at which to begin writing. + @param[in] NumBytes Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes actually written. + @param[in] Buffer Pointer to a caller allocated buffer that contains + the source for the write. + @retval EFI_SUCCESS The firmware volume was written successfully. + @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes + actually writte. + @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. + @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer are NULL. + +**/ +EFI_STATUS +FvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_FVB_ATTRIBUTES_2 Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_STATUS Status; + EFI_STATUS Status1; + + FwhInstance = GetFvbInstance (Instance); + + if ( (NumBytes == NULL) || (Buffer == NULL)) { + return (EFI_INVALID_PARAMETER); + } + if (*NumBytes == 0) { + return (EFI_INVALID_PARAMETER); + } + + Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Check if the FV is write enabled. + // + Attributes = FvbGetVolumeAttributes (Instance); + if ( (Attributes & EFI_FVB2_WRITE_STATUS) == 0) { + return (EFI_ACCESS_DENIED); + } + + // + // Perform boundary checks and adjust NumBytes. + // + if (BlockOffset > LbaLength) { + return (EFI_INVALID_PARAMETER); + } + + if ( LbaLength < ( *NumBytes + BlockOffset ) ) { + DEBUG ((EFI_D_ERROR, + "FvWriteBlock: Reducing Numbytes from 0x%x to 0x%x\n", + *NumBytes, + (UINT32)(LbaLength-BlockOffset)) + ); + *NumBytes = (UINT32) (LbaLength - BlockOffset); + Status = EFI_BAD_BUFFER_SIZE; + } + + LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, FALSE); + + Status1 = LibFvbFlashDeviceWrite (LbaAddress + BlockOffset, NumBytes, Buffer); + + LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, TRUE); + WriteBackInvalidateDataCacheRange ((VOID *) (LbaAddress + BlockOffset), *NumBytes); + + if ( EFI_ERROR (Status1) ) { + return Status1; + } + + return Status; +} + + +/** + Erases and initializes a firmware volume block. + + @param[in] Instance The FV instance to be erased. + @param[in] Lba The logical block index to be erased. + + @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. Firmware device may have been + partially erased. + @retval EFI_INVALID_PARAMETER Instance not found. + +**/ +EFI_STATUS +FvbEraseBlock ( + IN UINTN Instance, + IN EFI_LBA Lba + ) +{ + EFI_FVB_ATTRIBUTES_2 Attributes; + UINTN LbaAddress; + EFI_FW_VOL_INSTANCE *FwhInstance; + UINTN LbaLength; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data. + // + FwhInstance = GetFvbInstance (Instance); + + // + // Check if the FV is write enabled. + // + Attributes = FvbGetVolumeAttributes (Instance); + + if( (Attributes & EFI_FVB2_WRITE_STATUS) == 0) { + return (EFI_ACCESS_DENIED); + } + + // + // Get the starting address of the block for erase. + // + Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL); + if (EFI_ERROR(Status)) { + return Status; + } + + LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, FALSE); + + Status = LibFvbFlashDeviceBlockErase (LbaAddress, LbaLength); + + LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, TRUE); + + WriteBackInvalidateDataCacheRange ((VOID *) LbaAddress, LbaLength); + + return Status; +} + + +/** + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume. + + @param[in] Instance The FV instance whose attributes is going to be + modified. + @param[in] 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. + + @retval EFI_SUCCESS Successfully returns. + @retval EFI_ACCESS_DENIED The volume setting is locked and cannot be modified. + @retval EFI_INVALID_PARAMETER Instance not found, or The attributes requested are + in conflict with the capabilities as declared in the + firmware volume header. + +**/ +STATIC +EFI_STATUS +FvbSetVolumeAttributes ( + IN UINTN Instance, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_FW_VOL_INSTANCE *FwhInstance = NULL; + EFI_FVB_ATTRIBUTES_2 OldAttributes = 0; + EFI_FVB_ATTRIBUTES_2 *AttribPtr = NULL; + EFI_FVB_ATTRIBUTES_2 UnchangedAttributes; + UINT32 Capabilities; + UINT32 OldStatus, NewStatus; + + // + // Find the right instance of the FVB private data. + // + FwhInstance = GetFvbInstance (Instance); + + AttribPtr = (EFI_FVB_ATTRIBUTES_2 *) & (FwhInstance->VolumeHeader.Attributes); + ASSERT_EFI_ERROR (AttribPtr != NULL); + + if ( AttribPtr != NULL) { + OldAttributes = *AttribPtr; + } + + Capabilities = OldAttributes & EFI_FVB2_CAPABILITIES; + OldStatus = OldAttributes & EFI_FVB2_STATUS; + NewStatus = *Attributes & EFI_FVB2_STATUS; + + UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP | \ + EFI_FVB2_READ_ENABLED_CAP | \ + EFI_FVB2_WRITE_DISABLED_CAP | \ + EFI_FVB2_WRITE_ENABLED_CAP | \ + EFI_FVB2_LOCK_CAP | \ + EFI_FVB2_STICKY_WRITE | \ + EFI_FVB2_MEMORY_MAPPED | \ + EFI_FVB2_ERASE_POLARITY | \ + EFI_FVB2_READ_LOCK_CAP | \ + EFI_FVB2_WRITE_LOCK_CAP | \ + EFI_FVB2_ALIGNMENT; + + // + // Some attributes of FV is read only can *not* be set. + // + if ((OldAttributes & UnchangedAttributes) ^ (*Attributes & UnchangedAttributes)) { + return EFI_INVALID_PARAMETER; + } + + // + // If firmware volume is locked, no status bit can be updated. + // + if ( OldAttributes & EFI_FVB2_LOCK_STATUS ) { + if ( OldStatus ^ NewStatus ) { + return EFI_ACCESS_DENIED; + } + } + + // + // Test read disable. + // + if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) { + if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test read enable. + // + if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) { + if (NewStatus & EFI_FVB2_READ_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test write disable. + // + if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) { + if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test write enable. + // + if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) { + if (NewStatus & EFI_FVB2_WRITE_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test lock. + // + if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) { + if (NewStatus & EFI_FVB2_LOCK_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS)); + *AttribPtr = (*AttribPtr) | NewStatus; + *Attributes = *AttribPtr; + + return EFI_SUCCESS; +} + +// +// FVB protocol APIs. +// +/** + Retrieves the physical address of the device. + + @param[in] This A pointer to EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL. + @param[out] Address Output buffer containing the address. + + retval EFI_SUCCESS The function always return successfully. + +**/ +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FW_VOL_INSTANCE *FvInstance; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + FvInstance = GetFvbInstance(FvbDevice->Instance); + + if (FvInstance != NULL) { + *Address = FvInstance->FvBase; + } + + return EFI_SUCCESS; +} + + +/** + Retrieve the size of a logical block. + + @param[in] This Calling context. + @param[in] Lba Indicates which block to return the size for. + @param[out] BlockSize A pointer to a caller allocated UINTN in which + the size of the block is returned. + @param[out] 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. + + @retval EFI_SUCCESS The function always return successfully. + +**/ +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + DEBUG((EFI_D_INFO, + "FvbProtocolGetBlockSize: Lba: 0x%lx BlockSize: 0x%x NumOfBlocks: 0x%x\n", + Lba, + BlockSize, + NumOfBlocks) + ); + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbGetLbaAddress ( + FvbDevice->Instance, + Lba, + NULL, + BlockSize, + NumOfBlocks + ); +} + + +/** + Retrieves Volume attributes. No polarity translations are done. + + @param[in] This Calling context. + @param[out] Attributes Output buffer which contains attributes. + + @retval EFI_SUCCESS The function always return successfully. + +**/ +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + *Attributes = FvbGetVolumeAttributes (FvbDevice->Instance); + + DEBUG ((EFI_D_INFO, + "FvbProtocolGetAttributes: This: 0x%x Attributes: 0x%x\n", + This, + *Attributes) + ); + + return EFI_SUCCESS; +} + + +/** + Sets Volume attributes. No polarity translations are done. + + @param[in] This Calling context. + @param[out] Attributes Output buffer which contains attributes. + + @retval EFI_SUCCESS The function always return successfully. + +**/ +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_STATUS Status; + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + DEBUG((EFI_D_INFO, + "FvbProtocolSetAttributes: Before SET - This: 0x%x Attributes: 0x%x\n", + This, + *Attributes) + ); + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + Status = FvbSetVolumeAttributes (FvbDevice->Instance, Attributes); + + DEBUG((EFI_D_INFO, + "FvbProtocolSetAttributes: After SET - This: 0x%x Attributes: 0x%x\n", + This, + *Attributes) + ); + + return Status; +} + + +/** + 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. + + @param[in] This Calling context. + @param[in] ... Starting LBA followed by Number of Lba to erase. + a -1 to terminate the list. + + @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. Firmware device may have been + partially erased. + +**/ +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FW_VOL_INSTANCE *FwhInstance; + UINTN NumOfBlocks = 0; + VA_LIST args; + EFI_LBA StartingLba; + UINTN NumOfLba; + EFI_STATUS Status; + + DEBUG((EFI_D_INFO, "FvbProtocolEraseBlocks: \n")); + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + FwhInstance = GetFvbInstance (FvbDevice->Instance); + + if (FwhInstance != NULL) { + 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 ( 1 ); + + 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); + if ( EFI_ERROR(Status)) { + VA_END (args); + return Status; + } + StartingLba ++; + NumOfLba --; + } + + } while ( 1 ); + + VA_END (args); + + return EFI_SUCCESS; +} + + +/** + 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. + + @param[in] This Calling context. + @param[in] Lba Block in which to begin write. + @param[in] Offset Offset in the block at which to begin write. + @param[in,out] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Buffer containing source data for the write. + + @retval EFI_SUCCESS The firmware volume was written successfully. + @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes + actually written. + @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. + @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL. + +**/ +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_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + DEBUG((EFI_D_INFO, + "FvbProtocolWrite: Lba: 0x%lx Offset: 0x%x NumBytes: 0x%x, Buffer: 0x%x\n", + Lba, + Offset, + *NumBytes, + Buffer) + ); + + return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer); +} + + +/** + 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. + + @param[in] This Calling context. + @param[in] Lba Block in which to begin write. + @param[in] Offset Offset in the block at which to begin write + @param[in,out] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written. + @param[in] Buffer Buffer containing source data for the write. + + +Returns: + @retval EFI_SUCCESS The firmware volume was read successfully and + contents are in Buffer. + @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes returned + in Buffer. + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and + could not be read. + @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL. + +**/ +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + OUT UINT8 *Buffer + ) +{ + + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_STATUS Status; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + Status = FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer); + DEBUG((EFI_D_INFO, + "FvbProtocolRead: Lba: 0x%lx Offset: 0x%x NumBytes: 0x%x, Buffer: 0x%x\n", + Lba, + Offset, + *NumBytes, + Buffer) + ); + + return Status; +} + + +/** + Check the integrity of firmware volume header. + + @param[in] FwVolHeader A pointer to a firmware volume header. + + @retval TRUE The firmware volume is consistent. + @retval FALSE The firmware volume has corrupted. + +**/ +BOOLEAN +IsFvHeaderValid ( + IN EFI_PHYSICAL_ADDRESS FvBase, + IN CONST EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ) +{ + if (FvBase == PcdGet32(PcdFlashNvStorageVariableBase)) { + if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid, sizeof(EFI_GUID)) != 0 ) { + return FALSE; + } + } else { + if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) { + return FALSE; + } + } + if ( (FwVolHeader->Revision != EFI_FVH_REVISION) || + (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || + (FwVolHeader->FvLength == ((UINTN) -1)) || + ((FwVolHeader->HeaderLength & 0x01 ) !=0) ) { + return FALSE; + } + + if (CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength) != 0) { + return FALSE; + } + + return TRUE; +} + + +/** + The function does the necessary initialization work for + Firmware Volume Block Driver. + + @retval EFI_SUCCESS This funtion always return EFI_SUCCESS. + It will ASSERT on errors. + +**/ +EFI_STATUS +FvbInitialize ( + VOID + ) +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_STATUS Status; + UINTN BufferSize; + UINTN TmpHeaderLength; + UINTN Idx; + UINT32 MaxLbaSize; + BOOLEAN FvHeaderValid; + + // + // Calculate the total size for all firmware volume block instances. + // + BufferSize = 0; + for (Idx = 0; Idx < 1; Idx++) { + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) mPlatformFvBaseAddress[Idx]; + BufferSize += (FvHeader->HeaderLength + + sizeof (EFI_FW_VOL_INSTANCE) - + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + ); + } + + mFvbModuleGlobal.FvInstance = (EFI_FW_VOL_INSTANCE *) AllocateRuntimeZeroPool (BufferSize); + ASSERT (NULL != mFvbModuleGlobal.FvInstance); + + + MaxLbaSize = 0; + FwhInstance = mFvbModuleGlobal.FvInstance; + mFvbModuleGlobal.NumFv = 0; + + for (Idx = 0; Idx < 1; Idx++) { + BaseAddress = mPlatformFvBaseAddress[Idx]; + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; + + if (!IsFvHeaderValid (BaseAddress, FwVolHeader)) { + FvHeaderValid = FALSE; + // + // If not valid, get FvbInfo from the information carried in + // FVB driver. + // + DEBUG ((EFI_D_ERROR, "Fvb: FV header @ 0x%lx invalid\n", BaseAddress)); + Status = GetFvbInfo (BaseAddress, &FwVolHeader); + ASSERT_EFI_ERROR(Status); + // + // Write back a healthy FV header. + // + DEBUG ((EFI_D_ERROR, "FwBlockService.c: Writing back healthy FV header\n")); + LibFvbFlashDeviceBlockLock ((UINTN)BaseAddress, FwVolHeader->BlockMap->Length, FALSE); + + Status = LibFvbFlashDeviceBlockErase ((UINTN)BaseAddress, FwVolHeader->BlockMap->Length); + + TmpHeaderLength = (UINTN) FwVolHeader->HeaderLength; + Status = LibFvbFlashDeviceWrite ( + (UINTN)BaseAddress, + &TmpHeaderLength, + (UINT8 *) FwVolHeader + ); + + LibFvbFlashDeviceBlockLock ((UINTN)BaseAddress, FwVolHeader->BlockMap->Length, TRUE); + + WriteBackInvalidateDataCacheRange ( + (VOID *) (UINTN) BaseAddress, + FwVolHeader->BlockMap->Length + ); + + } + + CopyMem (&(FwhInstance->VolumeHeader), FwVolHeader, FwVolHeader->HeaderLength); + + FwVolHeader = &(FwhInstance->VolumeHeader); + FwhInstance->FvBase = (UINTN)BaseAddress; + + // + // Process the block map for each FV. + // + FwhInstance->NumOfBlocks = 0; + for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { + // + // Get the maximum size of a block. + // + if (MaxLbaSize < PtrBlockMapEntry->Length) { + MaxLbaSize = PtrBlockMapEntry->Length; + } + FwhInstance->NumOfBlocks += PtrBlockMapEntry->NumBlocks; + } + + // + // Add a FVB Protocol Instance. + // + mFvbModuleGlobal.NumFv++; + InstallFvbProtocol (FwhInstance, mFvbModuleGlobal.NumFv - 1); + + // + // Move on to the next FwhInstance. + // + FwhInstance = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhInstance) + + FwVolHeader->HeaderLength + + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))); + + } + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.h b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.h new file mode 100644 index 0000000000..cfdb92c5bc --- /dev/null +++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbService.h @@ -0,0 +1,187 @@ +/** @file + The header file for Firmware volume block driver. + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef _FW_BLOCK_SERVICE_H +#define _FW_BLOCK_SERVICE_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Define two helper macro to extract the Capability field or Status field in FVB +// bit fields. +// +#define EFI_FVB2_CAPABILITIES (EFI_FVB2_READ_DISABLED_CAP | \ + EFI_FVB2_READ_ENABLED_CAP | \ + EFI_FVB2_WRITE_DISABLED_CAP | \ + EFI_FVB2_WRITE_ENABLED_CAP | \ + EFI_FVB2_LOCK_CAP \ + ) + +#define EFI_FVB2_STATUS (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS) + + +typedef struct { + UINTN FvBase; + UINTN NumOfBlocks; + // + // Note!!!: VolumeHeader must be the last element + // of the structure. + // + EFI_FIRMWARE_VOLUME_HEADER VolumeHeader; +} EFI_FW_VOL_INSTANCE; + +typedef struct { + EFI_FW_VOL_INSTANCE *FvInstance; + UINT32 NumFv; +} FWB_GLOBAL; + +// +// 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') + +typedef struct { + MEDIA_FW_VOL_DEVICE_PATH FvDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_PIWG_DEVICE_PATH; + +typedef struct { + MEMMAP_DEVICE_PATH MemMapDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_MEMMAP_DEVICE_PATH; + +typedef struct { + UINT32 Signature; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN Instance; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance; +} EFI_FW_VOL_BLOCK_DEVICE; + +EFI_STATUS +GetFvbInfo ( + IN EFI_PHYSICAL_ADDRESS FvBaseAddress, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ); + +// +// 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 +EFIAPI +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, + OUT 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_FW_VOL_INSTANCE * +GetFvbInstance ( + IN UINTN Instance + ); + +BOOLEAN +IsFvHeaderValid ( + IN EFI_PHYSICAL_ADDRESS FvBase, + IN CONST EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ); + +VOID +InstallFvbProtocol ( + IN EFI_FW_VOL_INSTANCE *FwhInstance, + IN UINTN InstanceNum + ); + +EFI_STATUS +FvbInitialize ( + VOID + ); + +extern FWB_GLOBAL mFvbModuleGlobal; +extern EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate; +extern FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate; +extern FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate; +extern UINT32 mPlatformFvBaseAddress[3]; + +#endif + diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbServiceDxe.c b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbServiceDxe.c new file mode 100644 index 0000000000..3b45aa2001 --- /dev/null +++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbServiceDxe.c @@ -0,0 +1,204 @@ +/** @file + Firmware Volume Block Driver for Lakeport Platform. + + Firmware volume block driver for FWH or SPI device. + It depends on which Flash Device Library to be linked with this driver. + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include +#include +#include "FvbService.h" + +extern FWB_GLOBAL mFvbModuleGlobal; + +/** + Call back function on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event. + + Fixup internal data so that the driver is callable in EFI runtime + in virtual mode. Convert the mFvbModuleGlobal date items to there + virtual address. + + @param Event Event whose notification function is being invoked. + @param Context The context of the Notification context. Not used in + this call back function. + +**/ +VOID +EFIAPI +FvbVirtualddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + UINTN Index; + + // + // Convert the base address of all the instances. + // + for (Index = 0; Index < mFvbModuleGlobal.NumFv; Index++) { + FwhInstance = GetFvbInstance (Index); + EfiConvertPointer (0, (VOID **) &FwhInstance->FvBase); + } + + EfiConvertPointer (0, (VOID **) &mFvbModuleGlobal.FvInstance); +} + + +/** + The function installs EFI_FIRMWARE_VOLUME_BLOCK protocol + for each FV in the system. + + @param[in] FwhInstance The pointer to a FW volume instance structure, + which contains the information about one FV. + @param[in] InstanceNum The instance number which can be used as a ID + to locate this FwhInstance in other functions. + + @retval VOID + +**/ +VOID +InstallFvbProtocol ( + IN EFI_FW_VOL_INSTANCE *FwhInstance, + IN UINTN InstanceNum + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_STATUS Status; + EFI_HANDLE FwbHandle; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface; + + FvbDevice = (EFI_FW_VOL_BLOCK_DEVICE *) AllocateRuntimeCopyPool ( + sizeof (EFI_FW_VOL_BLOCK_DEVICE), + &mFvbDeviceTemplate + ); + ASSERT (FvbDevice != NULL); + + FvbDevice->Instance = InstanceNum; + FwVolHeader = &FwhInstance->VolumeHeader; + + // + // Set up the devicepath. + // + DEBUG ((EFI_D_INFO, "FwBlockService.c: Setting up DevicePath for 0x%lx:\n", FwhInstance->FvBase)); + if (FwVolHeader->ExtHeaderOffset == 0) { + // + // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH. + // + FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate); + ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.StartingAddress = FwhInstance->FvBase; + ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.EndingAddress = FwhInstance->FvBase + FwVolHeader->FvLength - 1; + } else { + FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate); + CopyGuid ( + &((FV_PIWG_DEVICE_PATH *)FvbDevice->DevicePath)->FvDevPath.FvName, + (GUID *)(UINTN)(FwhInstance->FvBase + FwVolHeader->ExtHeaderOffset) + ); + } + + // + // Find a handle with a matching device path that has supports FW Block protocol. + // + Status = gBS->LocateDevicePath ( + &gEfiFirmwareVolumeBlockProtocolGuid, + &FvbDevice->DevicePath, + &FwbHandle + ); + if (EFI_ERROR (Status) ) { + // + // LocateDevicePath fails so install a new interface and device path. + // + DEBUG ((EFI_D_INFO, "FwBlockService.c: LocateDevicePath failed, install new interface 0x%lx:\n", FwhInstance->FvBase)); + FwbHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + &FvbDevice->FwVolBlockInstance, + &gEfiDevicePathProtocolGuid, + FvbDevice->DevicePath, + NULL + ); + ASSERT_EFI_ERROR (Status); + DEBUG ((EFI_D_INFO, "FwBlockService.c: IMPI FirmwareVolBlockProt, DevPath 0x%lx: %r\n", FwhInstance->FvBase, Status)); + + } else if (IsDevicePathEnd (FvbDevice->DevicePath)) { + // + // Device allready exists, so reinstall the FVB protocol. + // + DEBUG ((EFI_D_ERROR, "FwBlockService.c: LocateDevicePath succeeded, reinstall interface 0x%lx:\n", FwhInstance->FvBase)); + Status = gBS->HandleProtocol ( + FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) &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); + } + +} + + +/** + The driver entry point for Firmware Volume Block Driver. + + The function does the necessary initialization work for + Firmware Volume Block Driver. + + @param[in] ImageHandle The firmware allocated handle for the UEFI image. + @param[in] SystemTable A pointer to the EFI system table. + + @retval EFI_SUCCESS This funtion always return EFI_SUCCESS. + It will ASSERT on errors. + +**/ +EFI_STATUS +EFIAPI +DxeFvbInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + FvbVirtualddressChangeEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &Event + ); + ASSERT_EFI_ERROR (Status); + + FvbInitialize (); + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbServiceSmm.c b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbServiceSmm.c new file mode 100644 index 0000000000..540e9f4ad5 --- /dev/null +++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbServiceSmm.c @@ -0,0 +1,132 @@ +/** @file + SMM Firmware Volume Block Driver for Lakeport Platform. + + Firmware volume block driver for FWH or SPI device. + It depends on which Flash Device Library to be linked with this driver. + +Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include +#include +#include "FvbSmmCommon.h" +#include "FvbService.h" + +/** + The function installs EFI_SMM_FIRMWARE_VOLUME_BLOCK protocol + for each FV in the system. + + @param[in] FwhInstance The pointer to a FW volume instance structure, + which contains the information about one FV. + @param[in] InstanceNum The instance number which can be used as a ID + to locate this FwhInstance in other functions. + + @retval VOID + +**/ +VOID +InstallFvbProtocol ( + IN EFI_FW_VOL_INSTANCE *FwhInstance, + IN UINTN InstanceNum + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_STATUS Status; + EFI_HANDLE FvbHandle; + + FvbDevice = (EFI_FW_VOL_BLOCK_DEVICE *) AllocateRuntimeCopyPool ( + sizeof (EFI_FW_VOL_BLOCK_DEVICE), + &mFvbDeviceTemplate + ); + ASSERT (FvbDevice != NULL); + + FvbDevice->Instance = InstanceNum; + FwVolHeader = &FwhInstance->VolumeHeader; + + // + // Set up the devicepath. + // + if (FwVolHeader->ExtHeaderOffset == 0) { + // + // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH. + // + FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate); + ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.StartingAddress = FwhInstance->FvBase; + ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.EndingAddress = FwhInstance->FvBase + FwVolHeader->FvLength - 1; + } else { + FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate); + CopyGuid ( + &((FV_PIWG_DEVICE_PATH *)FvbDevice->DevicePath)->FvDevPath.FvName, + (GUID *)(UINTN)(FwhInstance->FvBase + FwVolHeader->ExtHeaderOffset) + ); + } + + // + // Install the SMM Firmware Volume Block Protocol and Device Path Protocol. + // + FvbHandle = NULL; + Status = gSmst->SmmInstallProtocolInterface ( + &FvbHandle, + &gEfiSmmFirmwareVolumeBlockProtocolGuid, + EFI_NATIVE_INTERFACE, + &FvbDevice->FwVolBlockInstance + ); + ASSERT_EFI_ERROR (Status); + + Status = gSmst->SmmInstallProtocolInterface ( + &FvbHandle, + &gEfiDevicePathProtocolGuid, + EFI_NATIVE_INTERFACE, + FvbDevice->DevicePath + ); + ASSERT_EFI_ERROR (Status); + + // + // Notify the Fvb wrapper driver SMM fvb is ready. + // + FvbHandle = NULL; + Status = gBS->InstallProtocolInterface ( + &FvbHandle, + &gEfiSmmFirmwareVolumeBlockProtocolGuid, + EFI_NATIVE_INTERFACE, + &FvbDevice->FwVolBlockInstance + ); +} + + +/** + The driver entry point for SMM Firmware Volume Block Driver. + + The function does the necessary initialization work + Firmware Volume Block Driver. + + @param[in] ImageHandle The firmware allocated handle for the UEFI image. + @param[in] SystemTable A pointer to the EFI system table. + + @retval EFI_SUCCESS This funtion always return EFI_SUCCESS. + It will ASSERT on errors. + +**/ +EFI_STATUS +EFIAPI +FvbSmmInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + FvbInitialize (); + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmm.inf b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmm.inf new file mode 100644 index 0000000000..718ae0bbb2 --- /dev/null +++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmm.inf @@ -0,0 +1,87 @@ +## @file +# This driver implement the EFI_SMM_FIRMWARE_VOLUMEN_PROTOCOL. +# +# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FvbSmm + FILE_GUID = A4EC8ADB-B7A8-47d1-8E52-EC820D0ACF6F + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + ENTRY_POINT = FvbSmmInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# +# VIRTUAL_ADDRESS_MAP_CALLBACK = FvbVirtualddressChangeEvent +# + +[Sources] + FvbInfo.c + FvbService.h + FvbService.c + FvbServiceSmm.c + FvbSmmCommon.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + +[LibraryClasses] + FlashDeviceLib + PcdLib + MemoryAllocationLib + CacheMaintenanceLib + IoLib + BaseMemoryLib + DebugLib + BaseLib + UefiLib + SmmLib + SmmServicesTableLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Guids] + gEfiFirmwareFileSystem2Guid # ALWAYS_CONSUMED + gEfiSystemNvDataFvGuid # ALWAYS_CONSUMED + gEfiEventVirtualAddressChangeGuid + +[Protocols] + gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiSmmFirmwareVolumeBlockProtocolGuid # PROTOCOL ALWAYS_PRODUCED + +[FixedPcd] + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoveryBase + +[Pcd] + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainSize + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoverySize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + +[Depex] + gEfiSmmSpiProtocolGuid + diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmCommon.h b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmCommon.h new file mode 100644 index 0000000000..5660e0b78f --- /dev/null +++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmCommon.h @@ -0,0 +1,78 @@ +/** @file + + The common header file for SMM FVB module and SMM FVB runtime Module. + +Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef _SMM_FVB_COMMON_H_ +#define _SMM_FVB_COMMON_H_ + +#include + +#define EFI_FUNCTION_GET_ATTRIBUTES 1 +#define EFI_FUNCTION_SET_ATTRIBUTES 2 +#define EFI_FUNCTION_GET_PHYSICAL_ADDRESS 3 +#define EFI_FUNCTION_GET_BLOCK_SIZE 4 +#define EFI_FUNCTION_READ 5 +#define EFI_FUNCTION_WRITE 6 +#define EFI_FUNCTION_ERASE_BLOCKS 7 + +typedef struct { + UINTN Function; + EFI_STATUS ReturnStatus; + UINT8 Data[1]; +} SMM_FVB_COMMUNICATE_FUNCTION_HEADER; + + +/// +/// Size of SMM communicate header, without including the payload. +/// +#define SMM_COMMUNICATE_HEADER_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)) + +/// +/// Size of SMM FVB communicate function header, without including the payload. +/// +#define SMM_FVB_COMMUNICATE_HEADER_SIZE (OFFSET_OF (SMM_FVB_COMMUNICATE_FUNCTION_HEADER, Data)) + +typedef struct { + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + EFI_FVB_ATTRIBUTES_2 Attributes; +} SMM_FVB_ATTRIBUTES_HEADER; + +typedef struct { + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + EFI_PHYSICAL_ADDRESS Address; +} SMM_FVB_PHYSICAL_ADDRESS_HEADER; + +typedef struct { + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + EFI_LBA Lba; + UINTN BlockSize; + UINTN NumOfBlocks; +} SMM_FVB_BLOCK_SIZE_HEADER; + +typedef struct { + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + EFI_LBA Lba; + UINTN Offset; + UINTN NumBytes; +} SMM_FVB_READ_WRITE_HEADER; + +typedef struct { + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + EFI_LBA StartLba; + UINTN NumOfLba; +} SMM_FVB_BLOCKS_HEADER; + +#endif diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.c b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.c new file mode 100644 index 0000000000..20aaf8720f --- /dev/null +++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.c @@ -0,0 +1,949 @@ +/** @file + + Implement the Firmware Volume Block (FVB) services based on SMM FVB + module and install FVB protocol. + +Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include "FvbSmmDxe.h" + +EFI_HANDLE mHandle = NULL; +EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL; + +// +// Template structure used when installing FVB protocol. +// +EFI_FVB_DEVICE mFvbDeviceTemplate = { + FVB_DEVICE_SIGNATURE, + NULL, + { + FvbGetAttributes, + FvbSetAttributes, + FvbGetPhysicalAddress, + FvbGetBlockSize, + FvbRead, + FvbWrite, + FvbEraseBlocks, + NULL + }, + NULL +}; + +FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = { + { + { + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + { + (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), + (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) + } + }, + EfiMemoryMappedIO, + (EFI_PHYSICAL_ADDRESS) 0, + (EFI_PHYSICAL_ADDRESS) 0, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = { + { + { + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_VOL_DP, + { + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)), + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8) + } + }, + { 0 } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +/** + Initialize the communicate buffer using DataSize and Function. + + The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + + DataSize. + + @param[out] CommunicateBuffer The communicate buffer. Caller should free it after use. + @param[out] DataPtr Points to the data in the communicate buffer. Caller should not free it. + @param[in] DataSize The payload size. + @param[in] Function The function number used to initialize the communicate header. + + @retval EFI_INVALID_PARAMETER The data size is too big. + @retval EFI_SUCCESS Find the specified variable. + +**/ +EFI_STATUS +InitCommunicateBuffer ( + OUT VOID **CommunicateBuffer, + OUT VOID **DataPtr, + IN UINTN DataSize, + IN UINTN Function + ) +{ + EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; + SMM_FVB_COMMUNICATE_FUNCTION_HEADER *SmmFvbFunctionHeader; + + // + // The whole buffer size: SMM_COMMUNICATE_HEADER_SIZE + SMM_FVB_COMMUNICATE_HEADER_SIZE + DataSize. + // + SmmCommunicateHeader = AllocatePool (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_FVB_COMMUNICATE_HEADER_SIZE); + ASSERT (SmmCommunicateHeader != NULL); + + // + // Prepare data buffer. + // + CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmFirmwareVolumeBlockProtocolGuid); + SmmCommunicateHeader->MessageLength = DataSize + SMM_FVB_COMMUNICATE_HEADER_SIZE; + + SmmFvbFunctionHeader = (SMM_FVB_COMMUNICATE_FUNCTION_HEADER *) SmmCommunicateHeader->Data; + SmmFvbFunctionHeader->Function = Function; + + *CommunicateBuffer = SmmCommunicateHeader; + *DataPtr = SmmFvbFunctionHeader->Data; + + return EFI_SUCCESS; +} + + +/** + Send the data in communicate buffer to SMM. + + @param[out] SmmCommunicateHeader The communicate buffer. + @param[in] DataSize The payload size. + +**/ +EFI_STATUS +SendCommunicateBuffer ( + IN EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader, + IN UINTN DataSize + ) +{ + EFI_STATUS Status; + UINTN CommSize; + SMM_FVB_COMMUNICATE_FUNCTION_HEADER *SmmFvbFunctionHeader; + + CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_FVB_COMMUNICATE_HEADER_SIZE; + Status = mSmmCommunication->Communicate ( + mSmmCommunication, + SmmCommunicateHeader, + &CommSize + ); + ASSERT_EFI_ERROR (Status); + + SmmFvbFunctionHeader = (SMM_FVB_COMMUNICATE_FUNCTION_HEADER *) SmmCommunicateHeader->Data; + return SmmFvbFunctionHeader->ReturnStatus; +} + +/** + This function retrieves the attributes and current settings of the block. + + @param[in] This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[out] Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes + and current settings are returned. Type EFI_FVB_ATTRIBUTES_2 + is defined in EFI_FIRMWARE_VOLUME_HEADER. + + @retval EFI_SUCCESS The firmware volume attributes were returned. + @retval EFI_INVALID_PARAMETER Attributes is NULL. +**/ +EFI_STATUS +EFIAPI +FvbGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_STATUS Status; + UINTN PayloadSize; + EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; + SMM_FVB_ATTRIBUTES_HEADER *SmmFvbAttributesHeader; + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + EFI_FVB_DEVICE *FvbDevice; + + if (Attributes == NULL) { + return EFI_INVALID_PARAMETER; + } + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + SmmFvb = FvbDevice->SmmFvbInstance; + + // + // Initialize the communicate buffer. + // + PayloadSize = sizeof (SMM_FVB_ATTRIBUTES_HEADER); + Status = InitCommunicateBuffer ( + (VOID **)&SmmCommunicateHeader, + (VOID **)&SmmFvbAttributesHeader, + PayloadSize, + EFI_FUNCTION_GET_ATTRIBUTES + ); + if (EFI_ERROR (Status)) { + return Status; + } + + SmmFvbAttributesHeader->SmmFvb = SmmFvb; + SmmFvbAttributesHeader->Attributes = 0; + + // + // Send data to SMM. + // + Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize); + + // + // Get data from SMM. + // + *Attributes = SmmFvbAttributesHeader->Attributes; + FreePool (SmmCommunicateHeader); + + return Status; +} + + +/** + Sets Volume attributes. No polarity translations are done. + + @param[in] This Calling context. + @param[out] Attributes Output buffer which contains attributes. + + @retval EFI_SUCCESS Set the Attributes successfully. + @retval EFI_INVALID_PARAMETER Attributes is NULL. + +**/ +EFI_STATUS +EFIAPI +FvbSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_STATUS Status; + UINTN PayloadSize; + EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; + SMM_FVB_ATTRIBUTES_HEADER *SmmFvbAttributesHeader; + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + EFI_FVB_DEVICE *FvbDevice; + + if (Attributes == NULL) { + return EFI_INVALID_PARAMETER; + } + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + SmmFvb = FvbDevice->SmmFvbInstance; + + // + // Initialize the communicate buffer. + // + PayloadSize = sizeof (SMM_FVB_ATTRIBUTES_HEADER); + Status = InitCommunicateBuffer ( + (VOID **)&SmmCommunicateHeader, + (VOID **)&SmmFvbAttributesHeader, + PayloadSize, + EFI_FUNCTION_SET_ATTRIBUTES + ); + if (EFI_ERROR (Status)) { + return Status; + } + + SmmFvbAttributesHeader->SmmFvb = SmmFvb; + SmmFvbAttributesHeader->Attributes = *Attributes; + + // + // Send data to SMM. + // + Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize); + + // + // Get data from SMM. + // + *Attributes = SmmFvbAttributesHeader->Attributes; + FreePool (SmmCommunicateHeader); + + return Status; +} + + +/** + Retrieves the physical address of the FVB instance. + + @param[in] SmmFvb A pointer to EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL. + @param[out] Address Output buffer containing the address. + + @retval EFI_SUCCESS Get the address successfully. + @retval Others Failed to get address. + +**/ +EFI_STATUS +GetPhysicalAddress ( + IN EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + EFI_STATUS Status; + UINTN PayloadSize; + EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; + SMM_FVB_PHYSICAL_ADDRESS_HEADER *SmmFvbPhysicalAddressHeader; + + // + // Initialize the communicate buffer. + // + PayloadSize = sizeof (SMM_FVB_PHYSICAL_ADDRESS_HEADER); + Status = InitCommunicateBuffer ( + (VOID **)&SmmCommunicateHeader, + (VOID **)&SmmFvbPhysicalAddressHeader, + PayloadSize, + EFI_FUNCTION_GET_PHYSICAL_ADDRESS + ); + if (EFI_ERROR (Status)) { + return Status; + } + + SmmFvbPhysicalAddressHeader->SmmFvb = SmmFvb; + SmmFvbPhysicalAddressHeader->Address = 0; + + // + // Send data to SMM. + // + Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize); + + // + // Get data from SMM. + // + *Address = SmmFvbPhysicalAddressHeader->Address; + FreePool (SmmCommunicateHeader); + + return Status; +} + + +/** + Retrieves the physical address of the FVB instance. + + @param[in] This A pointer to EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL. + @param[out] Address Output buffer containing the address. + + @retval EFI_SUCCESS Get the address successfully. + @retval Others Failed to get the address. + +**/ +EFI_STATUS +EFIAPI +FvbGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + EFI_STATUS Status; + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + EFI_FVB_DEVICE *FvbDevice; + + if (Address == NULL) { + return EFI_INVALID_PARAMETER; + } + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + SmmFvb = FvbDevice->SmmFvbInstance; + + Status = GetPhysicalAddress (SmmFvb, Address); + + return Status; +} + + +/** + Retrieve the size of a logical block. + + @param[in] This Calling context. + @param[in] Lba Indicates which block to return the size for. + @param[out] BlockSize A pointer to a caller allocated UINTN in which + the size of the block is returned. + @param[out] 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. + + @retval EFI_SUCCESS Get BlockSize and NumOfBlocks successfully. + @retval EFI_INVALID_PARAMETER BlockSize or NumOfBlocks are NULL. +**/ +EFI_STATUS +EFIAPI +FvbGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +{ + EFI_STATUS Status; + UINTN PayloadSize; + EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; + SMM_FVB_BLOCK_SIZE_HEADER *SmmFvbBlockSizeHeader; + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + EFI_FVB_DEVICE *FvbDevice; + + if ((BlockSize == NULL) || (NumOfBlocks == NULL)) { + return EFI_INVALID_PARAMETER; + } + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + SmmFvb = FvbDevice->SmmFvbInstance; + + // + // Initialize the communicate buffer. + // + PayloadSize = sizeof (SMM_FVB_BLOCK_SIZE_HEADER); + Status = InitCommunicateBuffer ( + (VOID **)&SmmCommunicateHeader, + (VOID **)&SmmFvbBlockSizeHeader, + PayloadSize, + EFI_FUNCTION_GET_BLOCK_SIZE + ); + if (EFI_ERROR (Status)) { + return Status; + } + + SmmFvbBlockSizeHeader->SmmFvb = SmmFvb; + SmmFvbBlockSizeHeader->Lba = Lba; + + // + // Send data to SMM. + // + Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize); + + // + // Get data from SMM. + // + *BlockSize = SmmFvbBlockSizeHeader->BlockSize; + *NumOfBlocks = SmmFvbBlockSizeHeader->NumOfBlocks; + FreePool (SmmCommunicateHeader); + + return Status; +} + + +/** + 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. + + @param[in] This Calling context + @param[in] Lba Block in which to begin write + @param[in] Offset Offset in the block at which to begin write + @param[in,out] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Buffer containing source data for the write. + + @retval EFI_SUCCESS The firmware volume was read successfully and + contents are in Buffer. + @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes returned + in Buffer. + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and + could not be read. + @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL. + +**/ +EFI_STATUS +EFIAPI +FvbRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + OUT UINT8 *Buffer + ) +{ + EFI_STATUS Status; + UINTN PayloadSize; + EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; + SMM_FVB_READ_WRITE_HEADER *SmmFvbReadWriteHeader; + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + EFI_FVB_DEVICE *FvbDevice; + + if ((NumBytes == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + SmmFvb = FvbDevice->SmmFvbInstance; + + // + // Initialize the communicate buffer. + // + PayloadSize = sizeof (SMM_FVB_READ_WRITE_HEADER) + *NumBytes; + Status = InitCommunicateBuffer ( + (VOID **)&SmmCommunicateHeader, + (VOID **)&SmmFvbReadWriteHeader, + PayloadSize, EFI_FUNCTION_READ + ); + if (EFI_ERROR (Status)) { + return Status; + } + + SmmFvbReadWriteHeader->SmmFvb = SmmFvb; + SmmFvbReadWriteHeader->Lba = Lba; + SmmFvbReadWriteHeader->Offset = Offset; + SmmFvbReadWriteHeader->NumBytes = *NumBytes; + + // + // Send data to SMM. + // + Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize); + + // + // Get data from SMM. + // + *NumBytes = SmmFvbReadWriteHeader->NumBytes; + if (!EFI_ERROR (Status)) { + CopyMem (Buffer, (UINT8 *)(SmmFvbReadWriteHeader + 1), *NumBytes); + } + FreePool (SmmCommunicateHeader); + + return Status; +} + + +/** + 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. + + @param[in] This Calling context. + @param[in] Lba Block in which to begin write. + @param[in] Offset Offset in the block at which to begin write. + @param[in,out] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written. + @param[in] Buffer Buffer containing source data for the write. + + @retval EFI_SUCCESS The firmware volume was written successfully. + @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes + actually written. + @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. + @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL. + +**/ +EFI_STATUS +EFIAPI +FvbWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + UINTN PayloadSize; + EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; + SMM_FVB_READ_WRITE_HEADER *SmmFvbReadWriteHeader; + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + EFI_FVB_DEVICE *FvbDevice; + + if ((NumBytes == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + SmmFvb = FvbDevice->SmmFvbInstance; + + // + // Initialize the communicate buffer. + // + PayloadSize = sizeof (SMM_FVB_READ_WRITE_HEADER) + *NumBytes; + Status = InitCommunicateBuffer ( + (VOID **)&SmmCommunicateHeader, + (VOID **)&SmmFvbReadWriteHeader, + PayloadSize, + EFI_FUNCTION_WRITE + ); + if (EFI_ERROR (Status)) { + return Status; + } + + SmmFvbReadWriteHeader->SmmFvb = SmmFvb; + SmmFvbReadWriteHeader->Lba = Lba; + SmmFvbReadWriteHeader->Offset = Offset; + SmmFvbReadWriteHeader->NumBytes = *NumBytes; + CopyMem ((UINT8 *)(SmmFvbReadWriteHeader + 1), Buffer, *NumBytes); + + // + // Send data to SMM. + // + Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize); + + // + // Get data from SMM. + // + *NumBytes = SmmFvbReadWriteHeader->NumBytes; + FreePool (SmmCommunicateHeader); + + return Status; +} + + +/** + The EraseBlock() function erases NumOfLba blocks started from StartingLba. + + @param[in] This Calling context. + @param[in] StartingLba Starting LBA followed to erase. + @param[in] NumOfLba Number of block to erase. + + @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. Firmware device may have been + partially erased. + +**/ +EFI_STATUS +EraseBlock ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA StartingLba, + IN UINTN NumOfLba + ) +{ + EFI_STATUS Status; + UINTN PayloadSize; + EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; + SMM_FVB_BLOCKS_HEADER *SmmFvbBlocksHeader; + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + EFI_FVB_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + SmmFvb = FvbDevice->SmmFvbInstance; + + // + // Initialize the communicate buffer. + // + PayloadSize = sizeof (SMM_FVB_BLOCKS_HEADER); + Status = InitCommunicateBuffer ( + (VOID **)&SmmCommunicateHeader, + (VOID **)&SmmFvbBlocksHeader, + PayloadSize, + EFI_FUNCTION_ERASE_BLOCKS + ); + if (EFI_ERROR (Status)) { + return Status; + } + + SmmFvbBlocksHeader->SmmFvb = SmmFvb; + SmmFvbBlocksHeader->StartLba = StartingLba; + SmmFvbBlocksHeader->NumOfLba = NumOfLba; + + // + // Send data to SMM. + // + Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize); + + // + // Get data from SMM. + // + FreePool (SmmCommunicateHeader); + + return Status; +} + + +/** + The EraseBlocks() 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. + + @param[in] This Calling context/ + @param[in] ... Starting LBA followed by Number of Lba to erase. + a -1 to terminate the list. +/ + @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. Firmware device may have been + partially erased/ + +**/ +EFI_STATUS +EFIAPI +FvbEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +{ + EFI_STATUS Status; + VA_LIST Marker; + EFI_LBA StartingLba; + UINTN NumOfLba; + + Status = EFI_SUCCESS; + + // + // Check the parameter. + // + VA_START (Marker, This); + do { + StartingLba = VA_ARG (Marker, EFI_LBA); + if (StartingLba == EFI_LBA_LIST_TERMINATOR ) { + break; + } + + NumOfLba = VA_ARG (Marker, UINT32); + if (NumOfLba == 0) { + return EFI_INVALID_PARAMETER; + } + + } while ( 1 ); + VA_END (Marker); + + // + // Erase the blocks. + // + VA_START (Marker, This); + do { + StartingLba = VA_ARG (Marker, EFI_LBA); + if (StartingLba == EFI_LBA_LIST_TERMINATOR ) { + break; + } + NumOfLba = VA_ARG (Marker, UINT32); + Status = EraseBlock (This, StartingLba, NumOfLba); + if (EFI_ERROR (Status)) { + break; + } + } while ( 1 ); + VA_END (Marker); + + return Status; +} + + +/** + Install the FVB protocol which based on SMM FVB protocol. + + @param[in] SmmFvb The SMM FVB protocol. + +**/ +VOID +InstallFvb ( + IN EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb + ) +{ + EFI_STATUS Status; + EFI_HANDLE FvbHandle; + EFI_FVB_DEVICE *FvbDevice; + EFI_FIRMWARE_VOLUME_HEADER *VolumeHeader; + EFI_PHYSICAL_ADDRESS Address; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFvbInterface; + + FvbDevice = AllocateRuntimeCopyPool (sizeof (EFI_FVB_DEVICE), &mFvbDeviceTemplate); + ASSERT (FvbDevice != NULL); + FvbDevice->SmmFvbInstance = SmmFvb; + + Status = gBS->LocateProtocol ( + &gEfiSmmCommunicationProtocolGuid, + NULL, + (VOID **) &mSmmCommunication + ); + ASSERT_EFI_ERROR (Status); + + Status = GetPhysicalAddress (SmmFvb, &Address); + ASSERT_EFI_ERROR (Status); + + VolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN)Address; + + // + // Set up the devicepath. + // + if (VolumeHeader->ExtHeaderOffset == 0) { + // + // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH. + // + FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate); + ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.StartingAddress = (UINTN)Address; + ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.EndingAddress = (UINTN)Address + VolumeHeader->FvLength - 1; + } else { + FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate); + CopyGuid ( + &((FV_PIWG_DEVICE_PATH *)FvbDevice->DevicePath)->FvDevPath.FvName, + (GUID *)(UINTN)((UINTN)Address + VolumeHeader->ExtHeaderOffset) + ); + } + + // + // Find a handle with a matching device path that has supports FW Block protocol. + // + Status = gBS->LocateDevicePath ( + &gEfiFirmwareVolumeBlockProtocolGuid, + &FvbDevice->DevicePath, + &FvbHandle + ); + if (EFI_ERROR (Status) ) { + // + // LocateDevicePath fails so install a new interface and device path. + // + FvbHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &FvbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + &FvbDevice->FvbInstance, + &gEfiDevicePathProtocolGuid, + FvbDevice->DevicePath, + NULL + ); + ASSERT_EFI_ERROR (Status); + } else if (IsDevicePathEnd (FvbDevice->DevicePath)) { + // + // Device allready exists, so reinstall the FVB protocol. + // + Status = gBS->HandleProtocol ( + FvbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) &OldFvbInterface + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->ReinstallProtocolInterface ( + FvbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + OldFvbInterface, + &FvbDevice->FvbInstance + ); + ASSERT_EFI_ERROR (Status); + } else { + // + // There was a FVB protocol on an End Device Path node. + // + ASSERT (FALSE); + } +} + + +/** + SMM Firmware Volume Block Protocol notification event handler. + + Discover NV Variable Store and install Variable Write Arch Protocol. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification function's context. +**/ +VOID +EFIAPI +SmmFvbReady ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb; + + // + // Locate all handles of Smm Fvb protocol. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSmmFirmwareVolumeBlockProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return ; + } + + // + // Install FVB protocol. + // + for (Index = 0; Index < HandleCount; Index++) { + SmmFvb = NULL; + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiSmmFirmwareVolumeBlockProtocolGuid, + (VOID **) &SmmFvb + ); + if (EFI_ERROR (Status)) { + break; + } + + InstallFvb (SmmFvb); + } + + FreePool (HandleBuffer); +} + + +/** + The driver entry point for Firmware Volume Block Driver. + + The function does the necessary initialization work + Firmware Volume Block Driver. + + @param[in] ImageHandle The firmware allocated handle for the UEFI image. + @param[in] SystemTable A pointer to the EFI system table. + + @retval EFI_SUCCESS This funtion always return EFI_SUCCESS. + It will ASSERT on errors. + +**/ +EFI_STATUS +EFIAPI +FvbSmmDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + VOID *SmmFvbRegistration; + + // + // Smm FVB driver is ready. + // + EfiCreateProtocolNotifyEvent ( + &gEfiSmmFirmwareVolumeBlockProtocolGuid, + TPL_CALLBACK, + SmmFvbReady, + NULL, + &SmmFvbRegistration + ); + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.h b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.h new file mode 100644 index 0000000000..a34028f5da --- /dev/null +++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.h @@ -0,0 +1,237 @@ +/** @file + + The internal header file includes the common header files, defines + internal structure and functions used by FVB module. + +Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef _SMM_FVB_DXE_H_ +#define _SMM_FVB_DXE_H_ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "FvbSmmCommon.h" + +#define FVB_DEVICE_SIGNATURE SIGNATURE_32 ('F', 'V', 'B', 'S') +#define FVB_DEVICE_FROM_THIS(a) CR (a, EFI_FVB_DEVICE, FvbInstance, FVB_DEVICE_SIGNATURE) + +typedef struct { + MEDIA_FW_VOL_DEVICE_PATH FvDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_PIWG_DEVICE_PATH; + +typedef struct { + MEMMAP_DEVICE_PATH MemMapDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_MEMMAP_DEVICE_PATH; + +typedef struct { + UINTN Signature; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FvbInstance; + EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvbInstance; +} EFI_FVB_DEVICE; + +/** + This function retrieves the attributes and current settings of the block. + + @param[in] This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[out] Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes + and current settings are returned. Type EFI_FVB_ATTRIBUTES_2 + is defined in EFI_FIRMWARE_VOLUME_HEADER. + + @retval EFI_SUCCESS The firmware volume attributes were returned. + +**/ +EFI_STATUS +EFIAPI +FvbGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + + + /** + Sets Volume attributes. No polarity translations are done. + + @param[in] This Calling context. + @param[out] Attributes Output buffer which contains attributes. + + @retval EFI_SUCCESS The function always return successfully. + +**/ +EFI_STATUS +EFIAPI +FvbSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + + +/** + Retrieves the physical address of the device. + + @param[in] This A pointer to EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL. + @param[out] Address Output buffer containing the address. + + @retval EFI_SUCCESS The function always return successfully. + +**/ +EFI_STATUS +EFIAPI +FvbGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ); + + +/** + Retrieve the size of a logical block. + + @param[in] This Calling context. + @param[in] Lba Indicates which block to return the size for. + @param[out] BlockSize A pointer to a caller allocated UINTN in which + the size of the block is returned. + @param[out] 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. + + @retval EFI_SUCCESS The function always return successfully. + +**/ +EFI_STATUS +EFIAPI +FvbGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ); + + +/** + 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. + + @param[in] This Calling context. + @param[in] Lba Block in which to begin write. + @param[in] Offset Offset in the block at which to begin write + @param[in,out] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Buffer containing source data for the write. + + @retval EFI_SUCCESS The firmware volume was read successfully and + contents are in Buffer + @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes returned + in Buffer + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and + could not be read + @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL + +**/ +EFI_STATUS +EFIAPI +FvbRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + OUT UINT8 *Buffer + ); + + +/** + 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. + + @param[in] This Calling context. + @param[in] Lba Block in which to begin write. + @param[in] Offset Offset in the block at which to begin write. + @param[in,out] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Buffer containing source data for the write. + + @retval EFI_SUCCESS The firmware volume was written successfully + @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes + actually written. + @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. + @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL. + +**/ +EFI_STATUS +EFIAPI +FvbWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + + +/** + 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. + + @param[in] This Calling context. + @param[in] ... Starting LBA followed by Number of Lba to erase. + a -1 to terminate the list. + + @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. Firmware device may have been + partially erased. + +**/ +EFI_STATUS +EFIAPI +FvbEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ); + +#endif diff --git a/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.inf b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.inf new file mode 100644 index 0000000000..a588dc13e7 --- /dev/null +++ b/Vlv2TbltDevicePkg/FvbRuntimeDxe/FvbSmmDxe.inf @@ -0,0 +1,55 @@ +## @file +# Component description file for Firmware Volume Block module. +# +# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FvbSmmDxe + FILE_GUID = 9E8AD3F4-383D-4ec3-816E-7A4749371290 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = FvbSmmDxeInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + FvbSmmDxe.c + FvbSmmDxe.h + FvbSmmCommon.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + UefiBootServicesTableLib + DebugLib + DxeServicesTableLib + UefiDriverEntryPoint + PcdLib + +[Protocols] + gEfiFirmwareVolumeBlockProtocolGuid ## ALWAYS_PRODUCES + gEfiSmmCommunicationProtocolGuid + gEfiSmmFirmwareVolumeBlockProtocolGuid + +[Depex] + gEfiSmmCommunicationProtocolGuid diff --git a/Vlv2TbltDevicePkg/GenBiosId b/Vlv2TbltDevicePkg/GenBiosId new file mode 100644 index 0000000000000000000000000000000000000000..ef1578f2bcb8922905e0693035245c4329809aa7 GIT binary patch literal 12236 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 Oj(!g3>{OC7S^N)t{R~b3 literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/GenBiosId.exe b/Vlv2TbltDevicePkg/GenBiosId.exe new file mode 100644 index 0000000000000000000000000000000000000000..323b87c444915b173b7f32d5481c67e4471b047b GIT binary patch literal 384000 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 + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + AlertStandardFormatTable.h + +Abstract: + + ACPI Alert Standard Format Description Table ASF! as described + in the ASF2.0 Specification + +--*/ + +#ifndef _ALERT_STANDARD_FORMAT_TABLE_H +#define _ALERT_STANDARD_FORMAT_TABLE_H + +#include + +// +// Ensure proper structure formats. +// +#pragma pack (1) + +// +// Information Record header that appears at the beginning of each record. +// +typedef struct { + UINT8 Type; + UINT8 Reserved; + UINT16 RecordLength; +} EFI_ACPI_ASF_RECORD_HEADER; + +// +// This structure contains information that identifies the system type +// and configuration. +// +typedef struct { + EFI_ACPI_ASF_RECORD_HEADER RecordHeader; + UINT8 MinWatchDogResetValue; + UINT8 MinPollingInterval; + UINT16 SystemID; + UINT32 IANAManufactureID; + UINT8 FeatureFlags; + UINT8 Reserved[3]; +} EFI_ACPI_ASF_INFO; + +// +// Alert sensors definition. +// +#define ASF_ALRT_SENSOR_ARRAY_LENGTH 36 + +typedef struct { + EFI_ACPI_ASF_RECORD_HEADER RecordHeader; + UINT8 AssertionEventBitMask; + UINT8 DeassertionEventBitMask; + UINT8 NumberOfAlerts; + UINT8 ArrayElementLength; + UINT8 DeviceArray[ASF_ALRT_SENSOR_ARRAY_LENGTH]; +} EFI_ACPI_ASF_ALRT; + +// +// Alert Remote Control System Actions. +// +#define ASF_RCTL_DEVICES_ARRAY_LENGTH 16 + +typedef struct { + EFI_ACPI_ASF_RECORD_HEADER RecordHeader; + UINT8 NumberOfControls; + UINT8 ArrayElementLength; + UINT16 RctlReserved; + UINT8 ControlArray[ASF_RCTL_DEVICES_ARRAY_LENGTH]; +} EFI_ACPI_ASF_RCTL; + +// +// Remote Control Capabilities. +// +typedef struct { + EFI_ACPI_ASF_RECORD_HEADER RecordHeader; + UINT8 RemoteControlCapabilities[7]; + UINT8 RMCPCompletionCode; + UINT32 RMCPIANA; + UINT8 RMCPSpecialCommand; + UINT8 RMCPSpecialCommandParameter[2]; + UINT8 RMCPBootOptions[2]; + UINT8 RMCPOEMParameters[2]; +} EFI_ACPI_ASF_RMCP; + +// +// SMBus Devices with fixed addresses. +// +#define ASF_ADDR_DEVICE_ARRAY_LENGTH 16 + +typedef struct { + EFI_ACPI_ASF_RECORD_HEADER RecordHeader; + UINT8 SEEPROMAddress; + UINT8 NumberOfDevices; + UINT8 FixedSmbusAddresses[ASF_ADDR_DEVICE_ARRAY_LENGTH]; +} EFI_ACPI_ASF_ADDR; + +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_ASF_INFO AsfInfo; + EFI_ACPI_ASF_ALRT AsfAlert; + EFI_ACPI_ASF_RCTL AsfRctl; + EFI_ACPI_ASF_RMCP AsfRmcp; + EFI_ACPI_ASF_ADDR AsfAddr; +} EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE; + +// +// "ASF!" ASF Description Table Signature. +// +#define EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE_SIGNATURE 0x21465341 + +#pragma pack () + +#endif // _ALERT_STANDARD_FORMAT_TABLE_H diff --git a/Vlv2TbltDevicePkg/Include/ChipsetAccess.h b/Vlv2TbltDevicePkg/Include/ChipsetAccess.h new file mode 100644 index 0000000000..baf9b2905a --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/ChipsetAccess.h @@ -0,0 +1,33 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + ChipsetAccess.h + +Abstract: + + Common Include file for Platform Drivers to access the Chipset registers. + +--*/ + +#ifndef _CHIPSET_ACCESS_H_ +#define _CHIPSET_ACCESS_H_ + +#include "PchAccess.h" +#include "Valleyview.h" +#include "VlvAccess.h" +#include "VlvCommonDefinitions.h" + +#endif diff --git a/Vlv2TbltDevicePkg/Include/CommonIncludes.h b/Vlv2TbltDevicePkg/Include/CommonIncludes.h new file mode 100644 index 0000000000..04b5405806 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/CommonIncludes.h @@ -0,0 +1,120 @@ +/** + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +@file + CommonIncludes.h + +@brief + This file defines common equates. + +**/ +#ifndef _COMMON_INCLUDES_H_ +#define _COMMON_INCLUDES_H_ + +#define V_INTEL_VID 0x8086 + +#ifndef STALL_ONE_MICRO_SECOND +#define STALL_ONE_MICRO_SECOND 1 +#endif +#ifndef STALL_ONE_MILLI_SECOND +#define STALL_ONE_MILLI_SECOND 1000 +#endif +/// +/// Min Max +/// +#define V_MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define V_MAX(a, b) (((a) > (b)) ? (a) : (b)) + +/// +/// Bit map macro +/// +#ifndef BIT0 + +#define BIT63 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 + +#define BIT31 0x80000000 +#define BIT30 0x40000000 +#define BIT29 0x20000000 +#define BIT28 0x10000000 +#define BIT27 0x08000000 +#define BIT26 0x04000000 +#define BIT25 0x02000000 +#define BIT24 0x01000000 +#define BIT23 0x00800000 +#define BIT22 0x00400000 +#define BIT21 0x00200000 +#define BIT20 0x00100000 +#define BIT19 0x00080000 +#define BIT18 0x00040000 +#define BIT17 0x00020000 +#define BIT16 0x00010000 +#define BIT15 0x00008000 +#define BIT14 0x00004000 +#define BIT13 0x00002000 +#define BIT12 0x00001000 +#define BIT11 0x00000800 +#define BIT10 0x00000400 +#define BIT9 0x00000200 +#define BIT8 0x00000100 +#define BIT7 0x00000080 +#define BIT6 0x00000040 +#define BIT5 0x00000020 +#define BIT4 0x00000010 +#define BIT3 0x00000008 +#define BIT2 0x00000004 +#define BIT1 0x00000002 +#define BIT0 0x00000001 +#endif + +#define BITS(x) (1 << (x)) + +// +// Notes : +// 1. Bit position always starts at 0. +// 2. Following macros are applicable only for Word alligned integers. +// +#define BIT(Pos, Value) (1 << (Pos) & (Value)) +#define BITRANGE(From, Width, Value) (((Value) >> (From)) & ((1 << (Width)) - 1)) + +#endif diff --git a/Vlv2TbltDevicePkg/Include/CpuType.h b/Vlv2TbltDevicePkg/Include/CpuType.h new file mode 100644 index 0000000000..50562dc660 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/CpuType.h @@ -0,0 +1,64 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + CpuType.h + +Abstract: + +--*/ + +#ifndef _CPU_TYPE_H +#define _CPU_TYPE_H + +#pragma pack(1) + +typedef enum { + EnumCpuUarchUnknown = 0, + EnumNehalemUarch, +} EFI_CPU_UARCH; + +typedef enum { + EnumCpuPlatformUnknown = 0, + EnumDesktop, + EnumMobile, + EnumServer, + EnumNetTop +} EFI_CPU_PLATFORM; + +typedef enum { + EnumCpuTypeUnknown = 0, + EnumAtom, + EnumNehalemEx, + EnumBloomfield, + EnumGainestown, + EnumHavendale, + EnumLynnfield, + EnumAuburndale, + EnumClarksfield, + EnumPineview, + EnumCedarview, + EnumValleyview, + EnumClarkdale // Havendale 32nm +} EFI_CPU_TYPE; + +typedef enum { + EnumCpuFamilyUnknown = 0, + EnumFamilyField, + EnumFamilyDale +} EFI_CPU_FAMILY; + +#pragma pack() + +#endif diff --git a/Vlv2TbltDevicePkg/Include/FileHandleLib.h b/Vlv2TbltDevicePkg/Include/FileHandleLib.h new file mode 100644 index 0000000000..59d1b92355 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/FileHandleLib.h @@ -0,0 +1,504 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef _FILE_HANDLE_LIBRARY_HEADER_ +#define _FILE_HANDLE_LIBRARY_HEADER_ + +#include + +// +// The tag for use in identifying UNICODE files. +// If the file is UNICODE, the first 16 bits of the file will equal this value. +// +extern CONST UINT16 gUnicodeFileTag; + +/** + This function retrieves information about the file for the handle + specified and stores it in the allocated pool memory. + + This function allocates a buffer to store the file's information. It is the + caller's responsibility to free the buffer. + + @param[in] FileHandle The file handle of the file for which information is + being requested. + + @retval NULL Information could not be retrieved. + @retval !NULL The information about the file. +**/ +EFI_FILE_INFO* +EFIAPI +FileHandleGetInfo ( + IN EFI_FILE_HANDLE FileHandle + ); + +/** + This function sets the information about the file for the opened handle + specified. + + @param[in] FileHandle The file handle of the file for which information + is being set. + + @param[in] FileInfo The information to set. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER A parameter was out of range or invalid. + @retval EFI_UNSUPPORTED The FileHandle does not support FileInfo. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +FileHandleSetInfo ( + IN EFI_FILE_HANDLE FileHandle, + IN CONST EFI_FILE_INFO *FileInfo + ); + +/** + This function reads information from an opened file. + + If FileHandle is not a directory, the function reads the requested number of + bytes from the file at the file's current position and returns them in Buffer. + If the read goes beyond the end of the file, the read length is truncated to the + end of the file. The file's current position is increased by the number of bytes + returned. If FileHandle is a directory, the function reads the directory entry + at the file's current position and returns the entry in Buffer. If the Buffer + is not large enough to hold the current directory entry, then + EFI_BUFFER_TOO_SMALL is returned and the current file position is not updated. + BufferSize is set to be the size of the buffer needed to read the entry. On + success, the current position is updated to the next directory entry. If there + are no more directory entries, the read returns a zero-length buffer. + EFI_FILE_INFO is the structure returned as the directory entry. + + @param[in] FileHandle The opened file handle. + @param[in, out] BufferSize On input, the size of buffer in bytes. On return, + the number of bytes written. + @param[out] Buffer The buffer to put read data into. + + @retval EFI_SUCCESS Data was read. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required + size. + +**/ +EFI_STATUS +EFIAPI +FileHandleRead( + IN EFI_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + Write data to a file. + + This function writes the specified number of bytes to the file at the current + file position. The current file position is advanced the actual number of bytes + written, which is returned in BufferSize. Partial writes only occur when there + has been a data error during the write attempt (such as "volume space full"). + The file is automatically grown to hold the data if required. Direct writes to + opened directories are not supported. + + @param[in] FileHandle The opened file for writing. + @param[in, out] BufferSize On input, the number of bytes in Buffer. On output, + the number of bytes written. + @param[in] Buffer The buffer containing data to write is stored. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Writes to an open directory are not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write-protected. + @retval EFI_ACCESS_DENIED The file was opened for read only. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +FileHandleWrite( + IN EFI_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +/** + Close an open file handle. + + This function closes a specified file handle. All "dirty" cached file data is + flushed to the device, and the file is closed. In all cases the handle is + closed. + + @param[in] FileHandle The file handle to close. + + @retval EFI_SUCCESS The file handle was closed successfully. +**/ +EFI_STATUS +EFIAPI +FileHandleClose ( + IN EFI_FILE_HANDLE FileHandle + ); + +/** + Delete a file and close the handle. + + This function closes and deletes a file. In all cases the file handle is closed. + If the file cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is + returned, but the handle is still closed. + + @param[in] FileHandle The file handle to delete. + + @retval EFI_SUCCESS The file was closed successfully. + @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not + deleted. + @retval INVALID_PARAMETER One of the parameters has an invalid value. +**/ +EFI_STATUS +EFIAPI +FileHandleDelete ( + IN EFI_FILE_HANDLE FileHandle + ); + +/** + Set the current position in a file. + + This function sets the current file position for the handle to the position + supplied. With the exception of moving to position 0xFFFFFFFFFFFFFFFF, only + absolute positioning is supported, and moving past the end of the file is + allowed (a subsequent write would grow the file). Moving to position + 0xFFFFFFFFFFFFFFFF causes the current position to be set to the end of the file. + If FileHandle is a directory, the only position that may be set is zero. This + has the effect of starting the read process of the directory entries over again. + + @param[in] FileHandle The file handle on which the position is being set. + @param[in] Position The byte position from the begining of the file. + + @retval EFI_SUCCESS The operation completed sucessfully. + @retval EFI_UNSUPPORTED The request for non-zero is not valid on + directories. + @retval INVALID_PARAMETER One of the parameters has an invalid value. +**/ +EFI_STATUS +EFIAPI +FileHandleSetPosition ( + IN EFI_FILE_HANDLE FileHandle, + IN UINT64 Position + ); + +/** + Gets a file's current position. + + This function retrieves the current file position for the file handle. For + directories, the current file position has no meaning outside of the file + system driver. As such, the operation is not supported. An error is returned + if FileHandle is a directory. + + @param[in] FileHandle The open file handle on which to get the position. + @param[out] Position The byte position from begining of file. + + @retval EFI_SUCCESS The operation completed successfully. + @retval INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED The request is not valid on directories. +**/ +EFI_STATUS +EFIAPI +FileHandleGetPosition ( + IN EFI_FILE_HANDLE FileHandle, + OUT UINT64 *Position + ); + +/** + Flushes data on a file. + + This function flushes all modified data associated with a file to a device. + + @param[in] FileHandle The file handle on which to flush data. + + @retval EFI_SUCCESS The data was flushed. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened for read only. +**/ +EFI_STATUS +EFIAPI +FileHandleFlush ( + IN EFI_FILE_HANDLE FileHandle + ); + +/** + Function to determine if a given handle is a directory handle. + + If DirHandle is NULL, then ASSERT(). + + Open the file information on the DirHandle, and verify that the Attribute + includes EFI_FILE_DIRECTORY bit set. + + @param[in] DirHandle The handle to open the file. + + @retval EFI_SUCCESS DirHandle is a directory. + @retval EFI_INVALID_PARAMETER DirHandle did not have EFI_FILE_INFO available. + @retval EFI_NOT_FOUND DirHandle is not a directory. +**/ +EFI_STATUS +EFIAPI +FileHandleIsDirectory ( + IN EFI_FILE_HANDLE DirHandle + ); + +/** + Retrieve first entry from a directory. + + This function takes an open directory handle and gets information from the + first entry in the directory. A buffer is allocated to contain + the information and a pointer to the buffer is returned in *Buffer. The + caller can use FileHandleFindNextFile() to get subsequent directory entries. + + The buffer will be freed by FileHandleFindNextFile() when the last directory + entry is read. Otherwise, the caller must free the buffer, using FreePool, + when finished with it. + + @param[in] DirHandle The file handle of the directory to search. + @param[out] Buffer The pointer to pointer to buffer for file's information. + + @retval EFI_SUCCESS Found the first file. + @retval EFI_NOT_FOUND Cannot find the directory. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @return Others The status of FileHandleGetInfo, FileHandleSetPosition, + or FileHandleRead. +**/ +EFI_STATUS +EFIAPI +FileHandleFindFirstFile ( + IN EFI_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO **Buffer + ); + +/** + Retrieve next entries from a directory. + + To use this function, the caller must first call the FileHandleFindFirstFile() + function to get the first directory entry. Subsequent directory entries are + retrieved by using the FileHandleFindNextFile() function. This function can + be called several times to get each entry from the directory. If the call of + FileHandleFindNextFile() retrieved the last directory entry, the next call of + this function will set *NoFile to TRUE and free the buffer. + + @param[in] DirHandle The file handle of the directory. + @param[out] Buffer The pointer to buffer for file's information. + @param[out] NoFile The pointer to boolean when last file is found. + + @retval EFI_SUCCESS Found the next file, or reached last file. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. +**/ +EFI_STATUS +EFIAPI +FileHandleFindNextFile( + IN EFI_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO *Buffer, + OUT BOOLEAN *NoFile + ); + +/** + Retrieve the size of a file. + + If FileHandle is NULL then ASSERT(). + If Size is NULL then ASSERT(). + + This function extracts the file size info from the FileHandle's EFI_FILE_INFO + data. + + @param[in] FileHandle The file handle from which size is retrieved. + @param[out] Size The pointer to size. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR Cannot access the file. +**/ +EFI_STATUS +EFIAPI +FileHandleGetSize ( + IN EFI_FILE_HANDLE FileHandle, + OUT UINT64 *Size + ); + +/** + Set the size of a file. + + If FileHandle is NULL then ASSERT(). + + This function changes the file size info from the FileHandle's EFI_FILE_INFO + data. + + @param[in] FileHandle The file handle whose size is to be changed. + @param[in] Size The new size. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR Cannot access the file. +**/ +EFI_STATUS +EFIAPI +FileHandleSetSize ( + IN EFI_FILE_HANDLE FileHandle, + IN UINT64 Size + ); + +/** + Function to get a full filename given a EFI_FILE_HANDLE somewhere lower on the + directory 'stack'. + + @param[in] Handle Handle to the Directory or File to create path to. + @param[out] FullFileName Pointer to pointer to generated full file name. It + is the responsibility of the caller to free this memory + with a call to FreePool(). + @retval EFI_SUCCESS The operation was successful and FullFileName is valid. + @retval EFI_INVALID_PARAMETER Handle was NULL. + @retval EFI_INVALID_PARAMETER FullFileName was NULL. + @retval EFI_OUT_OF_MEMORY A memory allocation failed. +**/ +EFI_STATUS +EFIAPI +FileHandleGetFileName ( + IN CONST EFI_FILE_HANDLE Handle, + OUT CHAR16 **FullFileName + ); + +/** + Function to read a single line (up to but not including the \n) from a file. + + If the position upon start is 0, then the Ascii Boolean will be set. This should be + maintained and not changed for all operations with the same file. + + @param[in] Handle FileHandle to read from. + @param[in, out] Buffer The pointer to buffer to read into. + @param[in, out] Size The pointer to number of bytes in Buffer. + @param[in] Truncate If the buffer is large enough, this has no effect. + If the buffer is is too small and Truncate is TRUE, + the line will be truncated. + If the buffer is is too small and Truncate is FALSE, + then no read will occur. + + @param[in, out] Ascii Boolean value for indicating whether the file is + Ascii (TRUE) or UCS2 (FALSE). + + @retval EFI_SUCCESS The operation was successful. The line is stored in + Buffer. + @retval EFI_INVALID_PARAMETER Handle was NULL. + @retval EFI_INVALID_PARAMETER Size was NULL. + @retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line. + Size was updated to the minimum space required. + @sa FileHandleRead +**/ +EFI_STATUS +EFIAPI +FileHandleReadLine( + IN EFI_FILE_HANDLE Handle, + IN OUT CHAR16 *Buffer, + IN OUT UINTN *Size, + IN BOOLEAN Truncate, + IN OUT BOOLEAN *Ascii + ); + +/** + Function to read a single line from a file. The \n is not included in the returned + buffer. The returned buffer must be callee freed. + + If the position upon start is 0, then the Ascii Boolean will be set. This should be + maintained and not changed for all operations with the same file. + + @param[in] Handle FileHandle to read from. + @param[in, out] Ascii Boolean value for indicating whether the file is + Ascii (TRUE) or UCS2 (FALSE). + + @return The line of text from the file. + + @sa FileHandleReadLine +**/ +CHAR16* +EFIAPI +FileHandleReturnLine( + IN EFI_FILE_HANDLE Handle, + IN OUT BOOLEAN *Ascii + ); + +/** + Function to write a line of unicode text to a file. + + If Handle is NULL, ASSERT. + + @param[in] Handle FileHandle to write to. + @param[in] Buffer Buffer to write, if NULL the function will + take no action and return EFI_SUCCESS. + + @retval EFI_SUCCESS The data was written. + @retval other Failure. + + @sa FileHandleWrite +**/ +EFI_STATUS +EFIAPI +FileHandleWriteLine( + IN EFI_FILE_HANDLE Handle, + IN CHAR16 *Buffer + ); + +/** + Function to take a formatted argument and print it to a file. + + @param[in] Handle The file handle for the file to write to. + @param[in] Format The format argument (see printlib for the format specifier). + @param[in] ... The variable arguments for the format. + + @retval EFI_SUCCESS The operation was successful. + @retval other A return value from FileHandleWriteLine. + + @sa FileHandleWriteLine +**/ +EFI_STATUS +EFIAPI +FileHandlePrintLine( + IN EFI_FILE_HANDLE Handle, + IN CONST CHAR16 *Format, + ... + ); + +/** + Function to determine if a FILE_HANDLE is at the end of the file. + + This will NOT work on directories. + + If Handle is NULL, then ASSERT(). + + @param[in] Handle The file handle. + + @retval TRUE The position is at the end of the file. + @retval FALSE The position is not at the end of the file. +**/ +BOOLEAN +EFIAPI +FileHandleEof( + IN EFI_FILE_HANDLE Handle + ); + +#endif //_FILE_HANDLE_LIBRARY_HEADER_ + diff --git a/Vlv2TbltDevicePkg/Include/Guid/AcpiTableStorage.h b/Vlv2TbltDevicePkg/Include/Guid/AcpiTableStorage.h new file mode 100644 index 0000000000..663b26d4da --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/AcpiTableStorage.h @@ -0,0 +1,35 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + AcpiTableStorage.h + +Abstract: + + GUID for the ACPI Table Storage filename. + + This GUID is defined in the Tiano ACPI Table Storage EPS. + +--*/ + +#ifndef _ACPI_TABLE_STORAGE_H_ +#define _ACPI_TABLE_STORAGE_H_ + +#define EFI_ACPI_TABLE_STORAGE_GUID \ + { 0x7e374e25, 0x8e01, 0x4fee, {0x87, 0xf2, 0x39, 0xc, 0x23, 0xc6, 0x6, 0xcd} } + +extern EFI_GUID gEfiAcpiTableStorageGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Guid/AlertStandardFormat.h b/Vlv2TbltDevicePkg/Include/Guid/AlertStandardFormat.h new file mode 100644 index 0000000000..54df0b5b31 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/AlertStandardFormat.h @@ -0,0 +1,91 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + Asf.h + +Abstract: + + Alert Standard Format address variable + +--*/ + +#ifndef AlertStandardFormat_h_included +#define AlertStandardFormat_h_included + + +#pragma pack(1) + +// +// ASF address +// +// +// {3D995FB4-4F05-4073-BE72-A19CFB5DE690} +// +#define ALERT_STANDARD_FORMAT_VARIABLE_GUID \ + {0x3d995fb4, 0x4f05, 0x4073, 0xbe, 0x72, 0xa1, 0x9c, 0xfb, 0x5d, 0xe6, 0x90} + +#define ALERT_STANDARD_FORMAT_VARIABLE_NAME (L"ASF") +#define ASCII_ALERT_STANDARD_FORMAT_VARIABLE_NAME ("ASF") + +extern EFI_GUID gAlertStandardFormatGuid; +extern CHAR16 gAlertStandardFormatName[]; + +typedef struct { + UINT8 SmbusAddr; + struct { + UINT32 VendorSpecificId; + UINT16 SubsystemDeviceId; + UINT16 SubsystemVendorId; + UINT16 Interface; + UINT16 DeviceId; + UINT16 VendorId; + UINT8 VendorRevision; + UINT8 DeviceCapabilities; + } Udid; + struct { + UINT8 SubCommand; + UINT8 Version; + UINT32 IanaId; + UINT8 SpecialCommand; + UINT16 SpecialCommandParam; + UINT16 BootOptionsBits; + UINT16 OemParam; + } AsfBootOptions; + struct { + UINT8 Bus; + UINT8 Device; + UINT8 Function; + UINT16 VendorId; + UINT16 DeviceId; + UINT16 IderCmdBar; + UINT16 IderCtrlBar; + UINT8 IderIrq; + UINT16 SolBar; + UINT8 SolIrq; + } PciInfo; + struct { + UINT8 IamtProvisioningStatus; + BOOLEAN IamtIsProvisioned; + } IamtInfo; + struct { + BOOLEAN FlashUpdatingIsAllowed; + } MeInfoForEbu; + UINT32 EitBPFAddress; +} EFI_ASF_VARIABLE; + +#pragma pack() + +#endif + diff --git a/Vlv2TbltDevicePkg/Include/Guid/BiosId.h b/Vlv2TbltDevicePkg/Include/Guid/BiosId.h new file mode 100644 index 0000000000..15914b883e --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/BiosId.h @@ -0,0 +1,35 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + BiosId.h + +Abstract: + + GUIDs used for Bios ID. + +--*/ + +#ifndef _BIOS_ID_H_ +#define _BIOS_ID_H_ + + +#define EFI_BIOS_ID_GUID \ +{ 0xC3E36D09, 0x8294, 0x4b97, 0xA8, 0x57, 0xD5, 0x28, 0x8F, 0xE3, 0x3E, 0x28 } + + +extern EFI_GUID gEfiBiosIdGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Guid/BoardFeatures.h b/Vlv2TbltDevicePkg/Include/Guid/BoardFeatures.h new file mode 100644 index 0000000000..11bb98bb74 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/BoardFeatures.h @@ -0,0 +1,219 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + BoardFeatures.h + +Abstract: + + EFI Platform Board Features + + + +--*/ + +#ifndef BoardFeatures_h_included +#define BoardFeatures_h_included + +#include + +#pragma pack(1) + +// +// Board Features +// +#if defined LEGACY_BOARD_FEATURES && LEGACY_BOARD_FEATURES +#define B_BOARD_FEATURES_CHIPSET_LAN BIT0 +#define B_BOARD_FEATURES_LAN_MARVELL BIT1 +#define B_BOARD_FEATURES_AA_NOT_FOUND BIT2 +#define B_BOARD_FEATURES_SIO_NO_COM1 BIT3 +#define B_BOARD_FEATURES_SIO_COM2 BIT4 +#define B_BOARD_FEATURES_SIO_NO_PARALLEL BIT5 +#define B_BOARD_FEATURES_CHIPSET_VIDEO BIT6 +#define B_BOARD_FEATURES_CHIPSET_VIDEO_OPTION0 BIT7 +#define B_BOARD_FEATURES_VIDEO_SLOT BIT8 +#define B_BOARD_FEATURES_MINI_CARD BIT9 +#define B_BOARD_FEATURES_DISCRETE_1394 BIT10 +#define B_BOARD_FEATURES_LEGACY_FREE BIT11 +#define B_BOARD_FEATURES_USB_HUB BIT12 +#define B_BOARD_FEATURES_TPM BIT13 +#define B_BOARD_FEATURES_VIIV BIT14 +#define B_BOARD_FEATURES_FORM_FACTOR_MASK (BIT15|BIT16|BIT17|BIT18|BIT19) +#define B_BOARD_FEATURES_FORM_FACTOR_PBTX BIT15 +#define B_BOARD_FEATURES_FORM_FACTOR_ATX BIT16 +#define B_BOARD_FEATURES_FORM_FACTOR_BTX BIT17 +#define B_BOARD_FEATURES_FORM_FACTOR_MICRO_ATX BIT18 +#define B_BOARD_FEATURES_FORM_FACTOR_MICRO_BTX BIT19 +#define B_BOARD_FEATURES_MEMORY_TYPE_DDR1 BIT20 +#define B_BOARD_FEATURES_MEMORY_TYPE_DDR2 BIT21 +#define B_BOARD_FEATURES_MEMORY_SLOT_MASK BIT23 | BIT22 +#define V_BOARD_FEATURES_1_MEMORY_SLOT 0 // BIT22=0, BIT23=0 +#define V_BOARD_FEATURES_2_MEMORY_SLOT BIT22 // BIT22=1, BIT23=0 +#define V_BOARD_FEATURES_3_MEMORY_SLOT BIT23 // BIT22=0, BIT23=1 +#define V_BOARD_FEATURES_4_MEMORY_SLOT BIT23 | BIT22 // BIT22=1, BIT23=1 +#define B_BOARD_FEATURES_ALT_MEM_CLK_RT BIT24 +#define B_BOARD_FEATURES_SLEEP_MASK BIT25 +#define V_BOARD_FEATURES_SLEEP_S1 0 // BIT25=0 +#define V_BOARD_FEATURES_SLEEP_S3 BIT25 // BIT25=1 +#define B_BOARD_FEATURES_3JACK_AUDIO_SOLUTION BIT26 // 0/1= 5/3 Rear Jacks +#define B_BOARD_FEATURES_DISCRETE_SATA BIT27 +#define B_BOARD_FEATURES_2_SATA BIT28 // 2SATA instead of 4(pre Ich8) or 4 SATA instead of 6(Ich8) +#define B_BOARD_FEATURES_RVP BIT29 // Board is an RVP board +#define B_BOARD_FEATURES_PORT80_LPC BIT30 // Port80 PCI(0) or LPC(1) +#define B_BOARD_FEATURES_LIMITED_CPU_SUPPORT BIT31 // Limited CPU support +#define B_BOARD_FEATURES_PMP_SUPPORT BIT32 // Support for over-voltaging memory +#define B_BOARD_FEATURES_HW_WATCHDOG_TIMER BIT33 // Support for the HW-based 555 Watchdog Timer feature +#define B_BOARD_FEATURES_NO_QRT BIT34 // disable QRT +#define B_BOARD_FEATURES_VERB_TABLE1 BIT35 // Verb table 1 +#define B_BOARD_FEATURES_VERB_TABLE2 BIT36 // Verb table 2 +#define B_BOARD_FEATURES_VERB_TABLE3 BIT37 // Verb table 3 +#define B_BOARD_FEATURES_VERB_TABLE4 BIT38 // Verb table 4 +#define B_BOARD_FEATURES_VERB_TABLE5 BIT39 // Reserved for Verb table 5 +#define B_BOARD_FEATURES_VERB_TABLE_MASK BIT35 | BIT36 | BIT37 | BIT38 | BIT39 +#define B_BOARD_FEATURES_KENTSFIELD_BLOCK BIT40 // Kentsfield not supported +#define B_BOARD_FEATURES_KENTSFIELD_WARNING BIT41 // Kentsfield warning +#define B_BOARD_FEATURES_ESATA_PORT0 BIT42 // E-SATA on Port0 +#define B_BOARD_FEATURES_ESATA_PORT1 BIT43 // E-SATA on Port1 +#define B_BOARD_FEATURES_ESATA_PORT2 BIT44 // E-SATA on Port2 +#define B_BOARD_FEATURES_ESATA_PORT3 BIT45 // E-SATA on Port3 +#define B_BOARD_FEATURES_ESATA_PORT4 BIT46 // E-SATA on Port4 +#define B_BOARD_FEATURES_ESATA_PORT5 BIT47 // E-SATA on Port5 +#define B_BOARD_FEATURES_ECIR BIT48 // Enhanced Consumer IR +#define B_BOARD_FEATURES_PS2WAKEFROMS5 BIT49 // Wake from S5 via PS2 keyboard +#define B_BOARD_FEATURES_HDAUDIOLINK BIT50 // HD audio link support +#define B_BOARD_FEATURES_1_PATA BIT51 +#define B_BOARD_FEATURES_MOBILE BIT52 +#define B_BOARD_FEATURES_NO_FLOPPY BIT53 +#define B_BOARD_FEATURES_DISABLE_UNUSED_FSB BIT54 + +// +// Bit 55-58 reserved by PSID support. CPU power requirement below are preliminary. +// They might be changed. +// This is not same as 8.6.1 products so be careful. +// +#define B_BOARD_FEATURES_CPU_POWER_BITNUM 55 +#define B_BOARD_FEATURES_CPU_POWER_MASK (BIT55 | BIT56 | BIT57 | BIT58) +#define B_BOARD_FEATURES_CPU_POWER_35W 0 // Theoretically doesn't exist. +#define B_BOARD_FEATURES_CPU_POWER_40W BIT55 // 0001 +#define B_BOARD_FEATURES_CPU_POWER_45W BIT56 // 0010 +#define B_BOARD_FEATURES_CPU_POWER_50W (BIT55 | BIT56) // 0011 +#define B_BOARD_FEATURES_CPU_POWER_65W BIT57 // 0100 Wolfdale-H/-M +#define B_BOARD_FEATURES_CPU_POWER_70W (BIT55 | BIT57) // 0101 +#define B_BOARD_FEATURES_CPU_POWER_75W (BIT56 | BIT57) // 0110 +#define B_BOARD_FEATURES_CPU_POWER_80W (BIT55 | BIT56 | BIT57) // 0111 +#define B_BOARD_FEATURES_CPU_POWER_95W BIT58 // 1000 Yorkfield +#define B_BOARD_FEATURES_CPU_POWER_100W (BIT55 | BIT58) // 1001 +#define B_BOARD_FEATURES_CPU_POWER_105W (BIT56 | BIT58) // 1010 +#define B_BOARD_FEATURES_CPU_POWER_110W (BIT55 | BIT56 | BIT58) // 1011 +#define B_BOARD_FEATURES_CPU_POWER_130W (BIT57 | BIT58) // 1100 XE Yorkfield +#define B_BOARD_FEATURES_CPU_POWER_135W (BIT55 | BIT57 | BIT58) // 1101 +#define B_BOARD_FEATURES_CPU_POWER_Over135W (BIT56 | BIT57 | BIT58) // 1110 Reserved +#define B_BOARD_FEATURES_CPU_POWER_140W (BIT55 | BIT56 | BIT57 | BIT58) // 1111 Reserved +#define B_VV_BOARD_FEATURES BIT59 +#define B_BOARD_FEATURES_IDCC2_SUPPORT BIT60 // Include IDCC2 support +#define B_BOARD_FEATURES_NO_SATA_PORT2_3 BIT61 // No SATA Port2&3 Connector, used with B_BOARD_FEATURES_2_SATA flag +#define B_BOARD_FEATURES_FORM_FACTOR_MINI_ITX BIT62 +#define B_BOARD_FEATURES_NPI_QPI_VOLTAGE BIT63 + +#else + +#define B_BOARD_FEATURES_CHIPSET_LAN BIT0 +#define B_BOARD_FEATURES_CHIPSET_VIDEO BIT1 +#define B_BOARD_FEATURES_VIDEO_SLOT BIT2 +#define B_BOARD_FEATURES_AA_NOT_FOUND BIT3 +#define B_BOARD_FEATURES_SIO_NO_COM1 BIT4 +#define B_BOARD_FEATURES_SIO_COM2 BIT5 +#define B_BOARD_FEATURES_SIO_NO_PARALLEL BIT6 +#define B_BOARD_FEATURES_NO_FLOPPY BIT7 +#define B_BOARD_FEATURES_PS2WAKEFROMS5 BIT8 // Wake from S5 via PS2 keyboard +#define B_BOARD_FEATURES_ECIR BIT9 // Enhanced Consumer IR +#define B_BOARD_FEATURES_LEGACY_FREE BIT10 +#define B_BOARD_FEATURES_MINI_CARD BIT11 +#define B_BOARD_FEATURES_DISCRETE_1394 BIT12 +#define B_BOARD_FEATURES_USB_HUB BIT13 +#define B_BOARD_FEATURES_TPM BIT14 +#define B_BOARD_FEATURES_FORM_FACTOR_MASK (BIT15|BIT16|BIT17|BIT18|BIT19|BIT20) +#define B_BOARD_FEATURES_FORM_FACTOR_PBTX BIT15 +#define B_BOARD_FEATURES_FORM_FACTOR_ATX BIT16 +#define B_BOARD_FEATURES_FORM_FACTOR_BTX BIT17 +#define B_BOARD_FEATURES_FORM_FACTOR_MICRO_ATX BIT18 +#define B_BOARD_FEATURES_FORM_FACTOR_MICRO_BTX BIT19 +#define B_BOARD_FEATURES_FORM_FACTOR_MINI_ITX BIT20 +#define B_BOARD_FEATURES_MEMORY_TYPE_DDR2 BIT21 +#define B_BOARD_FEATURES_MEMORY_TYPE_DDR3 BIT22 +#define B_BOARD_FEATURES_MEMORY_SLOT_MASK (BIT24 | BIT23) +#define V_BOARD_FEATURES_1_MEMORY_SLOT 0 // BIT23=0, BIT24=0 +#define V_BOARD_FEATURES_2_MEMORY_SLOT BIT23 // BIT23=1, BIT24=0 +#define V_BOARD_FEATURES_3_MEMORY_SLOT BIT24 // BIT23=0, BIT24=1 +#define V_BOARD_FEATURES_4_MEMORY_SLOT (BIT24 | BIT23) // BIT23=1, BIT24=1 +#define B_BOARD_FEATURES_2_C0_MEMORY_SLOT BIT25 // 2 Channel 0 memory slot +#define B_BOARD_FEATURES_SLEEP_MASK BIT26 +#define V_BOARD_FEATURES_SLEEP_S1 0 // BIT26=0 +#define V_BOARD_FEATURES_SLEEP_S3 BIT26 // BIT26=1 +#define B_BOARD_FEATURES_3JACK_AUDIO_SOLUTION BIT27 // 0/1= 5/3 Rear Jacks +#define B_BOARD_FEATURES_HDAUDIOLINK BIT28 // HD audio link support +#define B_BOARD_FEATURES_DISCRETE_SATA BIT29 +#define B_BOARD_FEATURES_2_SATA BIT30 // 2SATA instead of 4(pre Ich8) or 4 SATA instead of 6(Ich8) +#define B_BOARD_FEATURES_NO_SATA_PORT2_3 BIT31 // No SATA Port2&3 Connector, used with B_BOARD_FEATURES_2_SATA flag +#define B_BOARD_FEATURES_RVP BIT32 // Board is an RVP board +#define B_BOARD_FEATURES_ESATA_PORT0 BIT33 // E-SATA on Port0 +#define B_BOARD_FEATURES_ESATA_PORT1 BIT34 // E-SATA on Port1 +#define B_BOARD_FEATURES_ESATA_PORT2 BIT35 // E-SATA on Port2 +#define B_BOARD_FEATURES_ESATA_PORT3 BIT36 // E-SATA on Port3 +#define B_BOARD_FEATURES_ESATA_PORT4 BIT37 // E-SATA on Port4 +#define B_BOARD_FEATURES_ESATA_PORT5 BIT38 // E-SATA on Port5 +#define B_BOARD_FEATURES_IDCC2_SUPPORT BIT39 // Include IDCC2 support +#define B_BOARD_FEATURES_NPI_QPI_VOLTAGE BIT40 +#define B_BOARD_FEATURES_LIMITED_CPU_SUPPORT BIT41 // Limited CPU support +#define B_BOARD_FEATURES_PMP_SUPPORT BIT42 // Support for over-voltaging memory +#define B_BOARD_FEATURES_HW_WATCHDOG_TIMER BIT43 // Support for the HW-based 555 Watchdog Timer feature +#define B_BOARD_FEATURES_LVDS BIT44 // Support for LVDS +#define B_BOARD_FEATURES_VERB_TABLE_MASK (BIT45|BIT46|BIT47|BIT48) // Verb table +#define B_BOARD_FEATURES_VERB_TABLE1 BIT45 // Verb table 1 +#define B_BOARD_FEATURES_VERB_TABLE2 BIT46 // Verb table 2 +#define B_BOARD_FEATURES_VERB_TABLE3 BIT47 // Verb table 3 +#define B_BOARD_FEATURES_VERB_TABLE4 BIT48 // Verb table 4 +#define B_BOARD_FEATURES_NO_MINIPCIE BIT49 // Mini PCIe slot +#define B_BOARD_FEATURES_HDMI_SLOT BIT50 // HDMI slot +#define B_BOARD_FEATURES_PS2_HIDE BIT51 // PS2 hide +#define B_BOARD_FEATURES_DVID_SLOT BIT52 // DVID slot + +#define B_BOARD_FEATURES_SIO_COM3 BIT53 +#define B_BOARD_FEATURES_SIO_COM4 BIT54 + +#define B_BOARD_FEATURES_LAN2 BIT55 +#define B_BOARD_FEATURES_PCIe_SLOT BIT56 +#endif + +typedef UINT64 EFI_BOARD_FEATURES; + +#pragma pack() + +// +// Global ID for the Platform Boot Mode Protocol. +// +#define EFI_BOARD_FEATURES_GUID \ + { 0x94b9e8ae, 0x8877, 0x479a, 0x98, 0x42, 0xf5, 0x97, 0x4b, 0x82, 0xce, 0xd3 } + +extern EFI_GUID gEfiBoardFeaturesGuid; + +#define BOARD_FEATURES_NAME L"BoardFeatures" + +#define EFI_BOARD_ID_GUID \ + { 0x6b2dd245, 0x3f2, 0x414a, 0x8c, 0x2, 0x9f, 0xfc, 0x23, 0x52, 0xe3, 0x1e } +#define EFI_BOARD_ID_NAME (L"BoardId") + +#endif + diff --git a/Vlv2TbltDevicePkg/Include/Guid/EfiVpdData.h b/Vlv2TbltDevicePkg/Include/Guid/EfiVpdData.h new file mode 100644 index 0000000000..31fa3e0511 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/EfiVpdData.h @@ -0,0 +1,161 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + EfiVpdData.h + +Abstract: + + Constants and declarations that are common accross PEI and DXE. +--*/ + +#ifndef _EFI_VPD_DATA_H_ +#define _EFI_VPD_DATA_H_ + + +#pragma pack(1) + +// +// DMI data +// +typedef struct { + + CHAR8 DmiGpnvHeader[4]; // $DMI + CHAR8 SystemInfoManufacturer[0x20]; // Structure Type 1 String 1 + CHAR8 SystemInfoProductName[0x20]; // Structure Type 1 String 2 + CHAR8 SystemInfoVersion[0x18]; // Structure Type 1 String 3 + CHAR8 SystemInfoSerialNumber[0x20]; // Structure Type 1 String 4 + CHAR8 BaseBoardManufacturer[0x20]; // Structure Type 2 String 1 + CHAR8 BaseBoardProductName[0x20]; // Structure Type 2 String 2 + CHAR8 BaseBoardVersion[0x18]; // Structure Type 2 String 3 + CHAR8 BaseBoardSerialNumber[0x20]; // Structure Type 2 String 4 + CHAR8 ChassisManufacturer[0x20]; // Structure Type 3 String 1 + UINT8 ChassisType; // Enumerated + CHAR8 ChassisVersion[0x18]; // Structure Type 3 String 2 + CHAR8 ChassisSerialNumber[0x20]; // Structure Type 3 String 3 + CHAR8 ChassisAssetTag[0x20]; // Structure Type 3 String 4 + UINT8 MfgAccessKeyWorkspace; + + UINT8 ChecksumFixupPool[0xd]; // Checksum Fix-ups + UINT8 SwitchboardData[4]; // 32 switch switchboard + UINT8 IntelReserved; // Reserved for Future Use +} DMI_DATA; + +#define DMI_DATA_GUID \ + { \ + 0x70e56c5e, 0x280c, 0x44b0, 0xa4, 0x97, 0x09, 0x68, 0x1a, 0xbc, 0x37, 0x5e \ + } + +#define DMI_DATA_NAME (L"DmiData") +#define ASCII_DMI_DATA_NAME ("DmiData") + +extern EFI_GUID gDmiDataGuid; +extern CHAR16 gDmiDataName[]; + +// +// UUID - universally unique system id. +// +#define UUID_VARIABLE_GUID \ + { \ + 0xd357c710, 0x0ada, 0x4717, 0x8d, 0xba, 0xc6, 0xad, 0xc7, 0xcd, 0x2b, 0x2a \ + } + +#define UUID_VARIABLE_NAME (L"UUID") +#define ASCII_UUID_VARIABLE_NAME ("UUID") + +// +// UUID data +// +typedef struct { + UINT32 UuidHigh; + UINT32 UuidLow; +} SYSTEM_1394_UUID; + +typedef struct { + EFI_GUID SystemUuid; // System Unique ID + SYSTEM_1394_UUID System1394Uuid; // Onboard 1394 UUID +} UUID_DATA; + +extern EFI_GUID gUuidVariableGuid; +extern CHAR16 gUuidVariableName[]; + +// +// MB32GUID for Computrace. +// + +#define MB32_GUID \ + { 0x539D62BA, 0xDE35, 0x453E, 0xBA, 0xB0, 0x85, 0xDB, 0x8D, 0xA2, 0x42, 0xF9 } + +#define MB32_VARIABLE_NAME (L"MB32") +#define ASCII_MB32_VARIABLE_NAME ("MB32") + +extern EFI_GUID gMb32Guid; +extern CHAR16 gMb32VariableName[]; + +// +// ACPI OSFR Manufacturer String. +// +// {72234213-0FD7-48a1-A59F-B41BC107FBCD} +// +#define ACPI_OSFR_MFG_STRING_VARIABLE_GUID \ + {0x72234213, 0xfd7, 0x48a1, 0xa5, 0x9f, 0xb4, 0x1b, 0xc1, 0x7, 0xfb, 0xcd} +#define ACPI_OSFR_MFG_STRING_VARIABLE_NAME (L"OcurMfg") +#define ASCII_ACPI_OSFR_MF_STRING_VARIABLE_NAME ("OcurMfg") + +extern EFI_GUID gACPIOSFRMfgStringVariableGuid; + + +// +// ACPI OSFR Model String. +// +// {72234213-0FD7-48a1-A59F-B41BC107FBCD} +// +#define ACPI_OSFR_MODEL_STRING_VARIABLE_GUID \ + {0x72234213, 0xfd7, 0x48a1, 0xa5, 0x9f, 0xb4, 0x1b, 0xc1, 0x7, 0xfb, 0xcd} +#define ACPI_OSFR_MODEL_STRING_VARIABLE_NAME (L"OcurModel") +#define ASCII_ACPI_OSFR_MODEL_STRING_VARIABLE_NAME ("OcurModel") + +extern EFI_GUID gACPIOSFRModelStringVariableGuid; + +// +// ACPI OSFR Reference Data Block. +// +// {72234213-0FD7-48a1-A59F-B41BC107FBCD} +// +#define ACPI_OSFR_REF_DATA_BLOCK_VARIABLE_GUID \ + {0x72234213, 0xfd7, 0x48a1, 0xa5, 0x9f, 0xb4, 0x1b, 0xc1, 0x7, 0xfb, 0xcd} +#define ACPI_OSFR_REF_DATA_BLOCK_VARIABLE_NAME (L"OcurRef") +#define ASCII_ACPI_OSFR_REF_DATA_BLOCK_VARIABLE_NAME ("OcurRef") +extern EFI_GUID gACPIOSFRRefDataBlockVariableGuid; + +// +// Manufacturing mode GUID +// +#define MfgMode_GUID \ + { 0xEF14FD78, 0x0793, 0x4e2b, 0xAC, 0x6D, 0x06, 0x28, 0x47, 0xE0, 0x17, 0x91 } + +#define MFGMODE_VARIABLE_NAME (L"MfgMode") +#define ASCII_MFGMODE_VARIABLE_NAME ("MfgMode") + +typedef struct { + UINT8 MfgModeData; +} MFG_MODE_VAR; + +extern EFI_GUID gMfgModeVariableGuid; +extern CHAR16 gMfgModeVariableName[]; + +#pragma pack() + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Guid/FirmwareId.h b/Vlv2TbltDevicePkg/Include/Guid/FirmwareId.h new file mode 100644 index 0000000000..061ded0f7a --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/FirmwareId.h @@ -0,0 +1,66 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + FirmwareId.h + +--*/ + +#ifndef _FirmwareId_h_GUID_included +#define _FirmwareId_h_GUID_included + + +#pragma pack(1) + +// +// Firmware ID +// + +#define FIRMWARE_ID_MAX_LENGTH 35 + +typedef struct { + CHAR8 BiosId[8]; + CHAR8 Separator1; + CHAR8 OemId[3]; + CHAR8 Separator2; + CHAR8 BuildId[4]; + CHAR8 Separator3; + CHAR8 Century[2]; + CHAR8 Year[2]; + CHAR8 Separator4; + CHAR8 Month[2]; + CHAR8 Date[2]; + CHAR8 Separator5; + CHAR8 Hour[2]; + CHAR8 Minute[2]; + CHAR8 Dummy[3]; +} FIRMWARE_ID_DATA; + +#define OLD_FIRMWARE_ID_GUID \ + {0xefc071ae, 0x41b8, 0x4018, 0xaf, 0xa7, 0x31, 0x4b, 0x18, 0x5e, 0x57, 0x8b} + +#define FIRMWARE_ID_GUID \ + {0x5e559c23, 0x1faa, 0x4ae1, 0x8d, 0x4a, 0xc6, 0xcf, 0x02, 0x6c, 0x76, 0x6f} + +#define FIRMWARE_ID_NAME L"FirmwareId" +#define FIRMWARE_ID_NAME_WITH_PASSWORD FIRMWARE_ID_NAME L"H#8,^-!t" + +extern EFI_GUID gFirmwareIdGuid; +extern CHAR16 gFirmwareIdName[]; + +#pragma pack() + +#endif + diff --git a/Vlv2TbltDevicePkg/Include/Guid/HwWatchdogTimerHob.h b/Vlv2TbltDevicePkg/Include/Guid/HwWatchdogTimerHob.h new file mode 100644 index 0000000000..cfb2228e2c --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/HwWatchdogTimerHob.h @@ -0,0 +1,139 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + HwWatchdogTimerHob.h + +Abstract: + + GUID used for Watchdog Timer status in the HOB list. + +--*/ + +#ifndef _EFI_WATCHDOG_TIMER_HOB_GUID_H_ +#define _EFI_WATCHDOG_TIMER_HOB_GUID_H_ + +#define EFI_WATCHDOG_TIMER_HOB_GUID \ + { 0x226cd3f, 0x69b5, 0x4150, 0xac, 0xbe, 0xbf, 0xbf, 0x18, 0xe3, 0x3, 0xd5 } + +#define EFI_WATCHDOG_TIMER_DEFINITION_HOB_GUID \ + { 0xd29302b0, 0x11ba, 0x4073, 0xa2, 0x27, 0x53, 0x8d, 0x25, 0x42, 0x70, 0x9f } + +typedef enum { + HWWD_NONE, + HWWD_TIMER_EXPIRED, + HWWD_SPONTANEOUS_REBOOT, + HWWD_FORCED_TIMEOUT +} HW_WATCHDOG_TIMEOUT; + +typedef struct { + HW_WATCHDOG_TIMEOUT TimeoutStatus; +} HW_WATCHDOG_INFO; + +// +// Watchdog timer action values. +// +#define WDT_ACTION_RESET 0x01 // reload/reset timer +#define WDT_ACTION_QUERY_CURRENT_VALUE 0x04 // get current value // DON'T NEED FOR OVERCLOCK UTILITY +#define WDT_ACTION_QUERY_COUNTDOWN_PERIOD 0x05 // get countdown period +#define WDT_ACTION_SET_COUNTDOWN_PERIOD 0x06 // set countdown period +#define WDT_ACTION_QUERY_RUNNING_STATE 0x08 // query if running +#define WDT_ACTION_SET_RUNNING_STATE 0x09 // start timer +#define WDT_ACTION_QUERY_STOPPED_STATE 0x0A // query if stopped +#define WDT_ACTION_SET_STOPPED_STATE 0x0B // stop timer +#define WDT_ACTION_QUERY_STATUS 0x20 // is current boot cause by wdt timeout? +#define WDT_ACTION_SET_STATUS 0x21 // resets wdt status bit + +// +// Watchdog timer instruction values. +// +#define WDT_INSTR_VALUE_MASK 0x03 // Mask for just the value +#define WDT_INSTR_READ_CMP_VALUE 0x00 // Read / compare value +#define WDT_INSTR_READ_COUNTDOWN 0x01 // read countdown value +#define WDT_INSTR_WRITE_VALUE 0x02 // Write value +#define WDT_INSTR_WRITE_COUNTDOWN 0x03 // write countdown value +#define WDT_INSTR_PRESERVE_REG 0x80 // preserve reg; used in Write Value / Write Countdown +#define WDT_INSTR_WRITE_VALUE_PRES (0x02 | WDT_INSTR_PRESERVE_REG) // Write value with preserve +#define WDT_INSTR_WRITE_COUNTDOWN_PRES (0x03 | WDT_INSTR_PRESERVE_REG) // write countdown value with preserve + +// +// The Generic Address Structure is defined in the ACPI Specification and should only be +// changed to match updated revisions of that specification. The GAS_ADDRESS_SPACE and +// GAS_ACCESS_SIZE enumerations are also defined by the ACPI Specification. +// +typedef enum { + GAS_SYSTEM_MEMORY, + GAS_SYSTEM_IO, + GAS_PCI_CONFIG_SPACE, + GAS_EMBEDDED_CONTROLLER, + GAS_SMBUS +} GAS_ADDRESS_SPACE; + +typedef enum { + GAS_UNDEFINED, + GAS_BYTE_ACCESS, + GAS_WORD_ACCESS, + GAS_DWORD_ACCESS, + GAS_QWORD_ACCESS +} GAS_ACCESS_SIZE; + +#pragma pack(1) + +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 AccessSize; + UINT64 Address; +} GENERIC_ADDRESS_STRUCTURE; + +// +// GAS_SYSTEM_MEMORY - When used as the AddressSpaceId, the 64-bit physical memory address +// of the register. 32-bit platforms must have the high DWORD set to 0. +// GAS_SYSTEM_IO - The 64-bit I/O address of the register. 32-bit platforms must have +// the high DWORD set to 0. +// GAS_PCI_CONFIG_SPACE - PCI Configuration space addresses must be confined to devices on PCI +// Sepment Group 0, Bus 0. This restriction exists to accommodate access +// to fixed hardware prior to PCI bus enumeration. The format of addresses +// are defined as follows: +// Highest WORD: Reserved and must be -0- +// ... PCI Device number on bus 0 +// ... PCI Function number +// Lowest WORD: Offset in the configuration space header. +// + +typedef struct { + UINT8 WdAction; + UINT8 Flag; + UINT16 Res; + GENERIC_ADDRESS_STRUCTURE GenericAddressStructures; + UINT32 Value; + UINT32 Mask; +} WD_INSTRUCTION; + +typedef struct { + UINT32 TimerPeriod; + UINT32 MaxTimerCount; + UINT32 MinTimerCount; + UINT16 InstructionCount; + WD_INSTRUCTION ActionDefinitions[1]; +} WD_HOB_DEFINITION; + +#pragma pack() + +extern EFI_GUID gWatchdogTimerHobGuid; +extern EFI_GUID gWatchdogTimerDefinitionHobGuid; + +#endif // _EFI_WATCHDOG_TIMER_HOB_GUID_H_ diff --git a/Vlv2TbltDevicePkg/Include/Guid/IdccData.h b/Vlv2TbltDevicePkg/Include/Guid/IdccData.h new file mode 100644 index 0000000000..fa8988b364 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/IdccData.h @@ -0,0 +1,109 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + IdccData.h + +Abstract: + +--*/ + +#ifndef _IDCCDATAHUB_GUID_H_ +#define _IDCCDATAHUB_GUID_H_ + +// +// This GUID is for the IDCC related data found in the Data Hub. +// +#define IDCC_DATA_HUB_GUID \ + { 0x788e1d9f, 0x1eab, 0x47d2, 0xa2, 0xf3, 0x78, 0xca, 0xe8, 0x7d, 0x60, 0x12 } + +extern EFI_GUID gIdccDataHubGuid; + +#pragma pack(1) + +typedef struct { + UINT32 Type; + UINT32 RecordLength; +} EFI_IDCC_DATA_HEADER; + +typedef struct { + EFI_IDCC_DATA_HEADER IdccHeader; + UINT32 Tcontrol; +} EFI_IDCC_TCONTROL; + +typedef struct { + UINT32 EntryCount; +} EFI_IDCC_CLOCK_COMMON; + +typedef struct { + UINT8 Polarity; + UINT8 Percent; + UINT32 FpValue; +} EFI_IDCC_TYPE_2_DATA; + +typedef struct { + UINT8 SetupVal; + UINT32 FpValue; +} EFI_IDCC_TYPE_3_4_DATA; + +typedef struct { + EFI_IDCC_DATA_HEADER IdccHeader; + UINT32 ProcessorRatio; +} EFI_IDCC_PROCESSOR_RATIO; + +typedef struct { + EFI_IDCC_DATA_HEADER IdccHeader; + UINT32 BoardFormFactor; +} EFI_IDCC_BOARD_FORM_FACTOR; + +typedef struct { + EFI_IDCC_DATA_HEADER IdccHeader; + UINT32 ProcessorInfo; +} EFI_IDCC_PROCESSOR_INFO; + +#define EFI_IDCC_PROCESSOR_UNCON (1 << 0) // Bit 0: UnCon CPU +#define EFI_IDCC_PROCESSOR_UNLOCK (1 << 1) // Bit 1: UnLock CPU +#define EFI_IDCC_PROCESSOR_CNR (1 << 2) // Bit 2: CNR CPU +#define EFI_IDCC_PROCESSOR_KNF (1 << 3) // Bit 3: KNF CPU + +typedef struct { + EFI_IDCC_DATA_HEADER IdccHeader; + UINT32 MinFSB; + UINT32 MaxFSB; + UINT8 StepFSB; +} EFI_IDCC_FSB_DATA; + +#pragma pack() + +#define EFI_IDCC_POSITIVE 0 +#define EFI_IDCC_NEGATIVE 1 + +// +// Board Form Factor equates. +// +#define ATX_FORM_FACTOR 0x00 +#define BTX_FORM_FACTOR 0x01 + + +#define EFI_IDCC_TCONTROL_TYPE 1 +#define EFI_IDCC_FSB_TYPE 2 +#define EFI_IDCC_PCI_TYPE 3 +#define EFI_IDCC_PCIE_TYPE 4 +#define EFI_IDCC_PROC_RATIO_TYPE 5 +#define EFI_IDCC_BOARD_FORM_FACTOR_TYPE 6 +#define EFI_IDCC_PROC_INFO_TYPE 7 +#define EFI_IDCC_FSB_DATA_TYPE 8 + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Guid/ItkData.h b/Vlv2TbltDevicePkg/Include/Guid/ItkData.h new file mode 100644 index 0000000000..3e02fd49cc --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/ItkData.h @@ -0,0 +1,75 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + ItkData.h + +Abstract: + +--*/ + +#ifndef _ITKDATAHUB_GUID_H_ +#define _ITKDATAHUB_GUID_H_ + +// +// This GUID is for the ITK related data found in the Data Hub {E7060843-A336-4d5b-9598-13402F5D7375} +// +#define ITK_DATA_HUB_GUID \ + { 0xe7060843, 0xa336, 0x4d5b, 0x95, 0x98, 0x13, 0x40, 0x2f, 0x5d, 0x73, 0x75 } + +extern EFI_GUID gItkDataHubGuid; + +// +// This GUID is for the ITK related data found in a Variable {3812723D-7E48-4e29-BC27-F5A39AC94EF1} +// +#define ITK_DATA_VAR_GUID \ + { 0x3812723d, 0x7e48, 0x4e29, 0xbc, 0x27, 0xf5, 0xa3, 0x9a, 0xc9, 0x4e, 0xf1 } + +extern EFI_GUID gItkDataVarGuid; + +#define ITK_DATA_VAR_NAME L"ItkDataVar" + +extern CHAR16 gItkDataVarName[]; + +#define ITK_BIOS_MOD_VAR_NAME L"ItkBiosModVar" + +extern CHAR16 gItkBiosModVarName[]; + +#pragma pack(1) +typedef struct { + UINT32 Type; + UINT32 RecordLength; +} EFI_ITK_DATA_HEADER; + +typedef struct { + EFI_ITK_DATA_HEADER ItkHeader; + UINT32 HecetaAddress; +} EFI_ITK_HECETA_ADDRESS; + +typedef struct { + UINT16 VarEqName; + UINT16 VarEqValue; +} EFI_ITK_VAR_EQ_RECORD; + +typedef struct { + EFI_ITK_DATA_HEADER ItkHeader; + EFI_ITK_VAR_EQ_RECORD VarEqRecord[0x10000]; +} EFI_ITK_VAR_EQ; +#pragma pack() + +#define EFI_ITK_HECETA_ADDRESS_TYPE 1 +#define EFI_ITK_MOBILE_BIOS_TYPE 2 +#define EFI_ITK_VAR_EQ_TYPE 3 + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Guid/MemoryConfigData.h b/Vlv2TbltDevicePkg/Include/Guid/MemoryConfigData.h new file mode 100644 index 0000000000..6780b3f924 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/MemoryConfigData.h @@ -0,0 +1,37 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +Module Name: + + MemoryConfigData.h + +Abstract: + + GUID used for Memory Configuration Data entries in the HOB list. + +--*/ + +#ifndef _MEMORY_CONFIG_DATA_GUID_H_ +#define _MEMORY_CONFIG_DATA_GUID_H_ + +#define EFI_MEMORY_CONFIG_DATA_GUID \ + { \ + 0x80dbd530, 0xb74c, 0x4f11, 0x8c, 0x03, 0x41, 0x86, 0x65, 0x53, 0x28, 0x31 \ + } + +extern EFI_GUID gEfiMemoryConfigDataGuid; +extern CHAR16 EfiMemoryConfigVariable[]; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Guid/OsSelection.h b/Vlv2TbltDevicePkg/Include/Guid/OsSelection.h new file mode 100644 index 0000000000..3e65ae659b --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/OsSelection.h @@ -0,0 +1,90 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + OsSelection.h + +Abstract: + + GUID used for LPSS, SCC and LPE configuration data entries in the HOB list. + +--*/ + +#ifndef _OS_SELECTION_GUID_H_ +#define _OS_SELECTION_GUID_H_ + +#ifndef ECP_FLAG +#include + +#include +#include +#include +#endif + +#define ANDROID 1 + +#define EFI_OS_SELECTION_VARIABLE_GUID \ + { \ + 0x86843f56, 0x675d, 0x40a5, 0x95, 0x30, 0xbc, 0x85, 0x83, 0x72, 0xf1, 0x03 \ + } + +extern EFI_GUID gOsSelectionVariableGuid; + +#pragma pack(1) + +typedef struct { + UINT8 LpssPciModeEnabled; + //SCC + UINT8 LpsseMMCEnabled; + UINT8 LpssSdioEnabled; + UINT8 LpssSdcardEnabled; + UINT8 LpssSdCardSDR25Enabled; + UINT8 LpssSdCardDDR50Enabled; + UINT8 LpssMipiHsi; + UINT8 LpsseMMC45Enabled; + UINT8 LpsseMMC45DDR50Enabled; + UINT8 LpsseMMC45HS200Enabled; + UINT8 LpsseMMC45RetuneTimerValue; + UINT8 eMMCBootMode; + //LPSS2 + UINT8 LpssDma1Enabled; + UINT8 LpssI2C0Enabled; + UINT8 LpssI2C1Enabled; + UINT8 LpssI2C2Enabled; + UINT8 LpssI2C3Enabled; + UINT8 LpssI2C4Enabled; + UINT8 LpssI2C5Enabled; + UINT8 LpssI2C6Enabled; + //LPSS1 + UINT8 LpssDma0Enabled; + UINT8 LpssPwm0Enabled; + UINT8 LpssPwm1Enabled; + UINT8 LpssHsuart0Enabled; + UINT8 LpssHsuart1Enabled; + UINT8 LpssSpiEnabled; + UINT8 I2CTouchAd; +} EFI_PLATFORM_LPSS_DATA; + +typedef struct _EFI_OS_SELECTION_HOB { + UINT8 OsSelection; + UINT8 OsSelectionChanged; + UINT8 Lpe; + UINT8 PchAzalia; + EFI_PLATFORM_LPSS_DATA LpssData; +} EFI_OS_SELECTION_HOB; + +#pragma pack() + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Guid/PciLanInfo.h b/Vlv2TbltDevicePkg/Include/Guid/PciLanInfo.h new file mode 100644 index 0000000000..775f71081c --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/PciLanInfo.h @@ -0,0 +1,44 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PciLanInfo.h + +Abstract: + +--*/ + +#ifndef _PCI_LAN_INFO_GUID_H_ +#define _PCI_LAN_INFO_GUID_H_ + +#pragma pack(1) + +// +// structure used for Pci Lan variable +// +typedef struct { + UINT8 PciBus; + UINT8 PciDevice; + UINT8 PciFunction; +} PCI_LAN_INFO; + +#pragma pack() + +#define EFI_PCI_LAN_INFO_GUID \ + {0xd9a1427, 0xe02a, 0x437d, 0x92, 0x6b, 0xaa, 0x52, 0x1f, 0xd7, 0x22, 0xba}; + +extern EFI_GUID gEfiPciLanInfoGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Guid/PlatformCpuInfo.h b/Vlv2TbltDevicePkg/Include/Guid/PlatformCpuInfo.h new file mode 100644 index 0000000000..ec9db67199 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/PlatformCpuInfo.h @@ -0,0 +1,185 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PlatformCpuInfo.h + +Abstract: + + GUID used for Platform CPU Info Data entries in the HOB list. + +--*/ + +#ifndef _PLATFORM_CPU_INFO_GUID_H_ +#define _PLATFORM_CPU_INFO_GUID_H_ + +#include "CpuType.h" +#include + +#define EFI_PLATFORM_CPU_INFO_GUID \ + {\ + 0xbb9c7ab7, 0xb8d9, 0x4bf3, 0x9c, 0x29, 0x9b, 0xf3, 0x41, 0xe2, 0x17, 0xbc \ + } + +extern EFI_GUID gEfiPlatformCpuInfoGuid; +extern CHAR16 EfiPlatformCpuInfoVariable[]; + +// +// Tri-state for feature capabilities and enable/disable. +// [0] clear=feature isn't capable +// [0] set =feature is capable +// [1] clear=feature is disabled +// [1] set =feature is enabled +// +#define CPU_FEATURES_CAPABLE BIT0 +#define CPU_FEATURES_ENABLE BIT1 + +#define MAX_CACHE_DESCRIPTORS 64 +#define MAXIMUM_CPU_BRAND_STRING_LENGTH 48 + +#pragma pack(1) + +typedef struct { + UINT32 FullCpuId; // [31:0] & 0x0FFF0FFF + UINT32 FullFamilyModelId; // [31:0] & 0x0FFF0FF0 + UINT8 ExtendedFamilyId; // [27:20] + UINT8 ExtendedModelId; // [19:16] + UINT8 ProcessorType; // [13:11] + UINT8 FamilyId; // [11:8] + UINT8 Model; // [7:4] + UINT8 SteppingId; // [3:0] +} EFI_CPU_VERSION_INFO; // CPUID.1.EAX + +typedef struct { + UINT32 L1InstructionCacheSize; + UINT32 L1DataCacheSize; + UINT32 L2CacheSize; + UINT32 L3CacheSize; + UINT32 TraceCacheSize; + UINT8 CacheDescriptor[MAX_CACHE_DESCRIPTORS]; +} EFI_CPU_CACHE_INFO; // CPUID.2.EAX + +typedef struct { + UINT8 PhysicalPackages; + UINT8 LogicalProcessorsPerPhysicalPackage; + UINT8 CoresPerPhysicalPackage; + UINT8 ThreadsPerCore; +} EFI_CPU_PACKAGE_INFO; // CPUID.4.EAX + +typedef struct { + UINT32 RegEdx; // CPUID.5.EAX + UINT8 MaxCState; + UINT8 C0SubCStatesMwait; // EDX [3:0] + UINT8 C1SubCStatesMwait; // EDX [7:4] + UINT8 C2SubCStatesMwait; // EDX [11:8] + UINT8 C3SubCStatesMwait; // EDX [15:12] + UINT8 C4SubCStatesMwait; // EDX [19:16] + UINT8 C5SubCStatesMwait; // EDX [23:20] + UINT8 C6SubCStatesMwait; // EDX [27:24] + UINT8 C7SubCStatesMwait; // EDX [31:28] + UINT8 MonitorMwaitSupport; // ECX [0] + UINT8 InterruptsBreakMwait; // ECX [1] +} EFI_CPU_CSTATE_INFO; // CPUID.5.EAX + +typedef struct { + UINT8 Turbo; // EAX [1] + UINT8 PECI; // EAX [0] + UINT8 NumIntThresholds; // EBX [3:0] + UINT8 HwCoordinationFeedback; // ECX [0] +} EFI_CPU_POWER_MANAGEMENT; // CPUID.6.EAX + +// +// IMPORTANT: Each CPU feature enabling entry is assumed a tri-state variable. +// - Keep the respective feature entry variable as default value (0x00) +// if the CPU is not capable for the feature. +// - Use the specially defined programming convention to update the variable +// to indicate capable, enable or disable. +// ie. F_CAPABLE for feature available +// F_ENABLE for feature enable +// F_DISABLE for feature disable +// +typedef struct { + EFI_CPUID_REGISTER Regs; // CPUID.1.EAX + UINT8 Xapic; // ECX [21] + UINT8 SSE4_2; // ECX [20] + UINT8 SSE4_1; // ECX [19] + UINT8 Dca; // ECX [18] + UINT8 SupSSE3; // ECX [9] + UINT8 Tm2; // ECX [8] + UINT8 Eist; // ECX [7] + UINT8 Lt; // ECX [6] + UINT8 Vt; // ECX [5] + UINT8 Mwait; // ECX [3] + UINT8 SSE3; // ECX [0] + UINT8 Tcc; // EDX [29] + UINT8 Mt; // EDX [28] + UINT8 SSE2; // EDX [26] + UINT8 SSE; // EDX [25] + UINT8 MMX; // EDX [23] + EFI_CPUID_REGISTER ExtRegs; // CPUID.80000001.EAX + UINT8 ExtLahfSahf64; // ECX [0] + UINT8 ExtIntel64; // EDX [29] + UINT8 ExtXd; // EDX [20] + UINT8 ExtSysCallRet64; // EDX [11] + UINT16 Ht; // CPUID.0B.EAX EBX [15:0] +} EFI_CPU_FEATURES; // CPUID.1.EAX, CPUID.0B.EAX, CPUID.80000001.EAX + +typedef struct { + UINT8 PhysicalBits; + UINT8 VirtualBits; +} EFI_CPU_ADDRESS_BITS; // CPUID.80000008.EAX + +typedef struct { + UINT8 PlatformID; // MSR 0x17 [52:50] + UINT32 MicrocodeRevision; // MSR 0x8B [63:32] + UINT8 MaxEfficiencyRatio; // MSR 0xCE [47:40] + UINT8 DdrRatioUnlockCap; // MSR 0xCE [30] + UINT8 TdcTdpLimitsTurbo; // MSR 0xCE [29] + UINT8 RatioLimitsTurbo; // MSR 0xCE [28] + UINT8 PreProduction; // MSR 0xCE [27] + UINT8 DcuModeSelect; // MSR 0xCE [26] + UINT8 MaxNonTurboRatio; // MSR 0xCE [15:8] + UINT8 Emrr; // MSR 0xFE [12] + UINT8 Smrr; // MSR 0xFE [11] + UINT8 VariableMtrrCount; // MSR 0xFE [7:0] + UINT16 PState; // MSR 0x198 [15:0] + UINT8 TccActivationTemperature; // MSR 0x1A2 [23:16] + UINT8 TemperatureControlOffset; // MSR 0x1A2 [15:8] + UINT32 PCIeBar; // MSR 0x300 [39:20] + UINT8 PCIeBarSizeMB; // MSR 0x300 [3:1] +} EFI_MSR_FEATURES; + +typedef struct { + BOOLEAN IsIntelProcessor; + UINT8 BrandString[MAXIMUM_CPU_BRAND_STRING_LENGTH + 1]; + UINT32 CpuidMaxInputValue; + UINT32 CpuidMaxExtInputValue; + EFI_CPU_UARCH CpuUarch; + EFI_CPU_FAMILY CpuFamily; + EFI_CPU_PLATFORM CpuPlatform; + EFI_CPU_TYPE CpuType; + EFI_CPU_VERSION_INFO CpuVersion; + EFI_CPU_CACHE_INFO CpuCache; + EFI_CPU_FEATURES CpuFeatures; + EFI_CPU_CSTATE_INFO CpuCState; + EFI_CPU_PACKAGE_INFO CpuPackage; + EFI_CPU_POWER_MANAGEMENT CpuPowerManagement; + EFI_CPU_ADDRESS_BITS CpuAddress; + EFI_MSR_FEATURES Msr; +} EFI_PLATFORM_CPU_INFO; + +#pragma pack() + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Guid/PlatformInfo.h b/Vlv2TbltDevicePkg/Include/Guid/PlatformInfo.h new file mode 100644 index 0000000000..0a73f0d748 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/PlatformInfo.h @@ -0,0 +1,437 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +Module Name: + + PlatformInfo.h + +Abstract: + + GUID used for Platform Info Data entries in the HOB list. + +--*/ + +#ifndef _PLATFORM_INFO_GUID_H_ +#define _PLATFORM_INFO_GUID_H_ + +#ifndef ECP_FLAG +#include + +#include +#include +#include +#include +#include +#endif + +#define PLATFORM_INFO_REVISION = 1 // Revision id for current platform information struct. + +// +// Start::BayLake Board Defines +// +#define BOARD_REVISION_DEFAULT = 0xff +#define UNKNOWN_FABID 0x0F +#define FAB_ID_MASK 0x0F +#define BOARD_ID_2 0x01 +#define BOARD_ID_1 0x40 +#define BOARD_ID_0 0x04 + +#define BOARD_ID_DT_CRB 0x0 +#define BOARD_ID_DT_VLVR 0x1 +#define BOARD_ID_SVP_VLV 0xC +#define BOARD_ID_SVP_EV_VLV 0xD +// +// End::BayLake Board Defines +// + +// +// Start::Alpine Valley Board Defines +// +#define DC_ID_DDR3L 0x00 +#define DC_ID_DDR3 0x04 +#define DC_ID_LPDDR3 0x02 +#define DC_ID_LPDDR2 0x06 +#define DC_ID_DDR4 0x01 +#define DC_ID_DDR3L_ECC 0x05 +#define DC_ID_NO_MEM 0x07 +// +// End::Alpine Valley Board Defines +// + +#define MAX_FAB_ID_RETRY_COUNT 100 +#define MAX_FAB_ID_CHECK_COUNT 3 + +#define PLATFORM_INFO_HOB_REVISION 0x1 + +#define EFI_PLATFORM_INFO_GUID \ + { \ + 0x1e2acc41, 0xe26a, 0x483d, 0xaf, 0xc7, 0xa0, 0x56, 0xc3, 0x4e, 0x8, 0x7b \ + } + +extern EFI_GUID gEfiPlatformInfoGuid; + +typedef enum { + FlavorUnknown = 0, + + // + // Mobile + // + FlavorMobile = 1, + + // + // Desktop + // + FlavorDesktop = 2, + + // + // Tablet + // + FlavorTablet = 3 +} PLATFORM_FLAVOR; + +#pragma pack(1) + +typedef struct { + UINT16 PciResourceIoBase; + UINT16 PciResourceIoLimit; + UINT32 PciResourceMem32Base; + UINT32 PciResourceMem32Limit; + UINT64 PciResourceMem64Base; + UINT64 PciResourceMem64Limit; + UINT64 PciExpressBase; + UINT32 PciExpressSize; + UINT8 PciHostAddressWidth; + UINT8 PciResourceMinSecBus; +} EFI_PLATFORM_PCI_DATA; + +typedef struct { + UINT8 CpuAddressWidth; + UINT32 CpuFamilyStepping; +} EFI_PLATFORM_CPU_DATA; + +typedef struct { + UINT8 SysIoApicEnable; + UINT8 SysSioExist; +} EFI_PLATFORM_SYS_DATA; + +typedef struct { + UINT32 MemTolm; + UINT32 MemMaxTolm; + UINT32 MemTsegSize; + UINT32 MemTsegBase; + UINT32 MemIedSize; + UINT32 MemIgdSize; + UINT32 MemIgdBase; + UINT32 MemIgdGttSize; + UINT32 MemIgdGttBase; + UINT64 MemMir0; + UINT64 MemMir1; + UINT32 MemConfigSize; + UINT16 MmioSize; + UINT8 DdrFreq; + UINT8 DdrType; + UINT32 MemSize; + BOOLEAN EccSupport; + UINT8 Reserved[3]; + UINT16 DimmSize[2]; +} EFI_PLATFORM_MEM_DATA; + + +typedef struct { + UINT32 IgdOpRegionAddress; // IGD OpRegion Starting Address + UINT8 IgdBootType; // IGD Boot Display Device + UINT8 IgdPanelType; // IGD Panel Type CMOs option + UINT8 IgdTvFormat; // IGD TV Format CMOS option + UINT8 IgdTvMinor; // IGD TV Minor Format CMOS option + UINT8 IgdPanelScaling; // IGD Panel Scaling + UINT8 IgdBlcConfig; // IGD BLC Configuration + UINT8 IgdBiaConfig; // IGD BIA Configuration + UINT8 IgdSscConfig; // IGD SSC Configuration + UINT8 IgdDvmtMemSize; // IGD DVMT Memory Size + UINT8 IgdFunc1Enable; // IGD Function 1 Enable + UINT8 IgdHpllVco; // HPLL VCO + UINT8 IgdSciSmiMode; // GMCH SMI/SCI mode (0=SCI) + UINT8 IgdPAVP; // IGD PAVP data +} EFI_PLATFORM_IGD_DATA; + +typedef enum { + BOARD_ID_AV_SVP = 0x0, // Alpine Valley Board + BOARD_ID_BL_RVP = 0x2, // BayLake Board (RVP) + BOARD_ID_BL_FFRD8 = 0x3, // FFRD8 b'0011 + BOARD_ID_BL_FFRD = 0x4, // BayLake Board (FFRD) + BOARD_ID_BL_RVP_DDR3L = 0x5, // BayLake Board (RVP DDR3L) + BOARD_ID_BL_STHI = 0x7, // PPV- STHI Board + BOARD_ID_BB_RVP = 0x20, // Bayley Bay Board + BOARD_ID_BS_RVP = 0x30, // Bakersport Board + BOARD_ID_CVH = 0x90, // Crestview Hills + BOARD_ID_MINNOW2 = 0xA0 // Minnow2 + +} BOARD_ID_LIST; + +typedef enum { + FAB1 = 0, + FAB2 = 1, + FAB3 = 2 +} FAB_ID_LIST; + +typedef enum { + PR0 = 0, // FFRD PR0 + PR05 = 1, // FFRD PR0.3 and PR 0.5 + PR1 = 2, // FFRD PR1 + PR11 = 3 // FFRD PR1.1 +} FFRD_ID_LIST; + + +// +// VLV2 GPIO GROUP OFFSET +// +#define GPIO_SCORE_OFFSET 0x0000 +#define GPIO_NCORE_OFFSET 0x1000 +#define GPIO_SSUS_OFFSET 0x2000 + +// +// GPIO Initialization Data Structure for BayLake. +// SC = SCORE, SS= SSUS +// Note: NC doesn't support GPIO functionality in IO access mode, only support in MMIO access mode. +// + +// +// IO space +// +typedef struct{ + UINT32 Use_Sel_SC0; + UINT32 Use_Sel_SC1; + UINT32 Use_Sel_SC2; + UINT32 Use_Sel_SS; + + UINT32 Io_Sel_SC0; + UINT32 Io_Sel_SC1; + UINT32 Io_Sel_SC2; + UINT32 Io_Sel_SS; + + UINT32 GP_Lvl_SC0; + UINT32 GP_Lvl_SC1; + UINT32 GP_Lvl_SC2; + UINT32 GP_Lvl_SS; + + UINT32 TPE_SC0; + UINT32 TPE_SS; + + UINT32 TNE_SC0; + UINT32 TNE_SS; + + UINT32 TS_SC0; + UINT32 TS_SS; + + UINT32 WE_SS; +} CFIO_INIT_STRUCT; + + + +// +// CFIO PAD configuration Registers +// +// +// Memory space +// +typedef union { + UINT32 dw; + struct { + UINT32 Func_Pin_Mux:3; // 0:2 Function of CFIO selection + UINT32 ipslew:2; // 3:4 Pad (P) Slew Rate Controls PAD slew rate check Width + UINT32 inslew:2; // 5:6 Pad (N) Slew Rate Controls PAD slew rate + UINT32 Pull_assign:2; // 7:8 Pull assignment + UINT32 Pull_strength:2; // 9:10 Pull strength + UINT32 Bypass_flop:1; // 11 Bypass flop + UINT32 Filter_en:1; // 12 Filter Enable + UINT32 Hist_ctrl:2; // 13:14 hysteresis control + UINT32 Hist_enb:1; // 15 Hysteresis enable, active low + UINT32 Delay_line:6; // 16:21 Delay line values - Delay values for input or output + UINT32 Reserved:3; // 22:24 Reserved + UINT32 TPE:1; // 25 Trigger Positive Edge Enable + UINT32 TNE:1; // 26 Trigger Negative Edge Enable + UINT32 Reserved2:3; // 27:29 Reserved + UINT32 i1p5sel:1; // 30 + UINT32 IODEN:1; // 31 : Open Drain enable. Active high + } r; +} PAD_CONF0; + +typedef union{ + UINT32 dw; + struct { + UINT32 instr:16; // 0:15 Pad (N) strength. + UINT32 ipstr:16; // 16:31 Pad (P) strength. + }r; +} PAD_CONF1; + +typedef union{ + UINT32 dw; + struct { + UINT32 pad_val:1; // 0 These registers are implemented as dual read/write with dedicated storage each. + UINT32 ioutenb:1; // 1 output enable + UINT32 iinenb:1; // 2 input enable + UINT32 Reserved:29; // 3:31 Reserved + }r; +} PAD_VAL; + +typedef union{ + UINT32 GPI; + struct { + UINT32 ihbpen:1; // 0 Pad high by pass enable + UINT32 ihbpinen:1; // 1 Pad high by pass input + UINT32 instaticen:1; // 2 TBD + UINT32 ipstaticen:1; // 3 TBD + UINT32 Overide_strap_pin :1; // 4 DFX indicates if it wants to override the strap pin value on this pad, if exists. + UINT32 Overide_strap_pin_val:1; // 5 In case DFX need to override strap pin value and it exist for the specific pad, this value will be used. + UINT32 TestMode_Pin_Mux:3; // 6:9 DFX Pin Muxing + }r; +} PAD_DFT; + +// +// GPIO_USAGE value need to matche the PAD_VAL input/output enable bits. +// +typedef enum { + Native = 0xFF, // Native, no need to set PAD_VALUE + GPI = 2, // GPI, input only in PAD_VALUE + GPO = 4, // GPO, output only in PAD_VALUE + GPIO = 0, // GPIO, input & output + TRISTS = 6, // Tri-State + GPIO_NONE +} GPIO_USAGE; + +typedef enum { + LO = 0, + HI = 1, + NA = 0xFF +} GPO_D4; + +typedef enum { + F0 = 0, + F1 = 1, + F2 = 2, + F3 = 3, + F4 = 4, + F5 = 5, + F6 = 6, + F7 = 7 +} GPIO_FUNC_NUM; + +// +// Mapping to CONF0 bit 27:24 +// Note: Assume "Direct Irq En" is not set, unless specially notified. +// +typedef enum { + TRIG_ = 0, + TRIG_Edge_High = /*BIT3 |*/ BIT1, // Positive Edge (Rasing) + TRIG_Edge_Low = /*BIT3 |*/ BIT2, // Negative Edge (Falling) + TRIG_Edge_Both = /*BIT3 |*/ BIT2 | BIT1, // Both Edge + TRIG_Level_High= /*BIT3 |*/ BIT1 | BIT0, // Level High + TRIG_Level_Low = /*BIT3 |*/ BIT2 | BIT0, // Level Low +} INT_TYPE; + +typedef enum { + P_20K_H, // Pull Up 20K + P_20K_L, // Pull Down 20K + P_10K_H, // Pull Up 10K + P_10K_L, // Pull Down 10K + P_2K_H, // Pull Up 2K + P_2K_L, // Pull Down 2K + P_NONE // Pull None +} PULL_TYPE; + +#ifdef EFI_DEBUG + #define GPIO_INIT_ITEM(pad_name, usage, gpod4, func, int_cap, int_type, pull, offset) {pad_name, usage, gpod4, func, /*int_cap,*/ TRIG_##int_type, P_##pull, offset} +#else + #define GPIO_INIT_ITEM(pad_name, usage, gpod4, func, int_cap, int_type, pull, offset) { usage, gpod4, func, /*int_cap,*/ TRIG_##int_type, P_##pull, offset} +#endif + +// +// GPIO CONF & PAD Initialization Data Structure for BayLake GPIOs bits. +// NC = NCORE, SC = SCORE, SS= SSUS +// +typedef struct { + +#ifdef EFI_DEBUG + char pad_name[32];// GPIO Pin Name for debug purpose +#endif + + GPIO_USAGE usage; // GPIO pin used as Native mode or GPI/GPO/GPIO mode + GPO_D4 gpod4; // GPO default value + GPIO_FUNC_NUM func; // Function Number (F0~F7) + INT_TYPE int_type; // Edge or Level trigger, low or high active + PULL_TYPE pull; // Pull Up or Down + UINT8 offset; // Equal with (PCONF0 register offset >> 4 bits) +} GPIO_CONF_PAD_INIT; + +// +//typedef UINT64 BOARD_FEATURES +// +typedef struct _EFI_PLATFORM_INFO_HOB { + UINT16 PlatformType; // Platform Type + UINT8 BoardId; // Board ID + UINT8 BoardRev; // Board Revision + PLATFORM_FLAVOR PlatformFlavor; // Platform Flavor + UINT8 DDRDaughterCardCh0Id;// DDR daughter card channel 0 id + UINT8 DDRDaughterCardCh1Id;// DDR daughter card channel 1 id + UINT8 ECOId; // ECO applied on platform + UINT16 IohSku; + UINT8 IohRevision; + UINT16 IchSku; + UINT8 IchRevision; + EFI_PLATFORM_PCI_DATA PciData; + EFI_PLATFORM_CPU_DATA CpuData; + EFI_PLATFORM_MEM_DATA MemData; + EFI_PLATFORM_SYS_DATA SysData; + EFI_PLATFORM_IGD_DATA IgdData; + UINT8 RevisonId; // Structure Revision ID + EFI_PHYSICAL_ADDRESS PlatformCfioData; + EFI_PHYSICAL_ADDRESS PlatformGpioData_NC; + EFI_PHYSICAL_ADDRESS PlatformGpioData_SC; + EFI_PHYSICAL_ADDRESS PlatformGpioData_SUS; + EFI_PHYSICAL_ADDRESS PlatformGpioData_NC_TRI; + EFI_PHYSICAL_ADDRESS PlatformGpioData_SC_TRI; + EFI_PHYSICAL_ADDRESS PlatformGpioData_SUS_TRI; + EFI_PHYSICAL_ADDRESS PlatformGpioData_SUS_PR1; + EFI_PHYSICAL_ADDRESS PlatformGpioData_SC_PR1_1; + EFI_PHYSICAL_ADDRESS PlatformGpioData_SUS_PR1_1; + + UINT8 CfioEnabled; + UINT32 SsidSvid; + UINT16 AudioSubsystemDeviceId; + UINT64 AcpiOemId; + UINT64 AcpiOemTableId; + UINT16 MemCfgID; +} EFI_PLATFORM_INFO_HOB; + +#pragma pack() + +EFI_STATUS +GetPlatformInfoHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT EFI_PLATFORM_INFO_HOB **PlatformInfoHob + ); + + +EFI_STATUS +InstallPlatformClocksNotify ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +InstallPlatformSysCtrlGPIONotify ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Guid/SensorInfoVariable.h b/Vlv2TbltDevicePkg/Include/Guid/SensorInfoVariable.h new file mode 100644 index 0000000000..b058e3ceb5 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/SensorInfoVariable.h @@ -0,0 +1,284 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +Module Name: + + SensorInfoVariable.h + +Abstract: + + GUID used for Sensor Info variable. + +--*/ + + +// +// Module: SensorInfoVariable.h +// +// Description: Provides structure and literal definitions for the +// Sensor Information Variable. The BIOS will provide +// this variable to runtime applications via the EFI +// GetVariable function. +// +// Notes: 1. When defining and initializing the variable within the +// BIOS, the module will define the structure using the +// typedef macros in a block. For an ATX board using a +// single Heceta 6P, which has 4 temperature sensors, 6 +// voltage sensors, 4 fan speed sensors and 3 fan speed +// controllers, this block would be declared as follows: +// +// TYPEDEF_TEMP_SENSOR_SECTION(4); +// TYPEDEF_VOLT_SENSOR_SECTION(6); +// TYPEDEF_FAN_SENSOR_SECTION(4); +// TYPEDEF_FAN_CONTROLLER_SENSOR(3); +// TYPEDEF_SENSOR_INFO_VAR; +// +// 2. When crafting code to access the variable, the module +// will also need to invoke the typedef macros in a +// block but, since it cannot declare a structure for the +// overall variable (because array lengths will vary), it +// cannot use TYPEDEF_SENSOR_INFO_VAR. The block will +// typically be used as follows: +// +// TYPEDEF_TEMP_SENSOR_SECTION(1); +// TYPEDEF_VOLT_SENSOR_SECTION(1); +// TYPEDEF_FAN_SENSOR_SECTION(1); +// TYPEDEF_FAN_CONTROLLER_SENSOR(1); +// +// The structure buffer should instead be declared as a +// BYTE array. Pointers to the various sections can then +// be built using the XXXX_SECTION_LEN macros... +// + + +#ifndef _SENSOR_INFO_VAR_GUID_H_ +#define _SENSOR_INFO_VAR_GUID_H_ + +#define SENSOR_INFO_VAR_GUID \ + { \ + 0xE59E7B4D, 0x06DC, 0x44AB, 0xB3, 0x6D, 0x5E, 0xD7, 0x78, 0x9C, 0x53, 0x0A \ + } + +extern EFI_GUID gEfiSensorInfoVarGuid; +extern CHAR16 gEfiSensorInfoVarName[]; +extern CHAR16 gEfiSensorInfoVarNameWithPassword[]; + +#define SENSOR_INFO_VAR_NAME L"SensorInfoVar" +#define SENSOR_INFO_VAR_NAME_WITH_PASSWORD SENSOR_INFO_VAR_NAME L"S4k?A^7!" + +// +// Sensor/Controller usage definitions +// + +#define UNKNOWN_OTHER 0 + +// +// Temperature Sensors +// +#define CPU_CORE_TEMPERATURE 1 +#define CPU_DIE_TEMPERATURE 2 +#define ICH_TEMPERATURE 3 +#define MCH_TEMPERATURE 4 +#define VR_TEMPERATURE 5 +#define MEMORY_TEMPERATURE 6 +#define MOTHERBOARD_AMBIENT_TEMPERATURE 7 +#define SYSTEM_AMBIENT_AIR_TEMPERATURE 8 +#define CPU_INLET_AIR_TEMPERATURE 9 +#define SYSTEM_INLET_AIR_TEMPERATURE 10 +#define SYSTEM_OUTLET_AIR_TEMPERATURE 11 +#define PSU_HOTSPOT_TEMPERATURE 12 +#define PSU_INLET_AIR_TEMPERATURE 13 +#define PSU_OUTLET_AIR_TEMPERATURE 14 +#define DRIVE_TEMPERATURE 15 +#define GPU_TEMPERATURE 16 +#define IOH_TEMPERATURE 17 + +#define LAST_TEMPERATURE 17 + +// +// Voltage Sensors +// +#define PLUS_12_VOLTS 1 +#define NEG_12_VOLTS 2 +#define PLUS_5_VOLTS 3 +#define PLUS_5_VOLT_BACKUP 4 +#define NEG_5_VOLTS 5 +#define PLUS_3P3_VOLTS 6 +#define PLUS_2P5_VOLTS 7 +#define PLUS_1P5_VOLTS 8 +#define CPU_1_VCCP_VOLTAGE 9 +#define CPU_2_VCCP_VOLTAGE 10 +#define CPU_3_VCCP_VOLTAGE 11 +#define CPU_4_VCCP_VOLTAGE 12 +#define PSU_INPUT_VOLTAGE 13 +#define MCH_VCC_VOLTAGE 14 +#define PLUS_3P3_VOLT_STANDBY 15 +#define CPU_VTT_VOLTAGE 16 +#define PLUS_1P8_VOLTS 17 + +#define LAST_VOLTAGE 17 + +// +// Fan Speed Sensors and Controllers. +// +#define CPU_COOLING_FAN 1 +#define SYSTEM_COOLING_FAN 2 +#define MCH_COOLING_FAN 3 +#define VR_COOLING_FAN 4 +#define CHASSIS_COOLING_FAN 5 +#define CHASSIS_INLET_FAN 6 +#define CHASSIS_OUTLET_FAN 7 +#define PSU_COOLING_FAN 8 +#define PSU_INLET_FAN 9 +#define PSU_OUTLET_FAN 10 +#define DRIVE_COOLING_FAN 11 +#define GPU_COOLING_FAN 12 +#define AUX_COOLING_FAN 13 +#define IOH_COOLING_FAN 14 + +#define LAST_FAN 14 + +// +// Fan Type Definitions +// +#define FAN_TYPE_UNKNOWN 0 +#define FAN_3WIRE_PULSE 1 +#define FAN_3WIRE_VOLTAGE 2 +#define FAN_4WIRE 3 + +#pragma pack(1) + +// +// TEMP_SENSOR_INFO - Structure providing info for a temperature sensor. +// +typedef struct _TEMP_SENSOR_INFO +{ + UINT8 byDevice; // Device index + UINT8 byIndex; // Physical sensor index + UINT8 byUsage; // Usage indicator + UINT8 bRelative; // Relative vs. Absolute readings + +} TEMP_SENSOR_INFO, *P_TEMP_SENSOR_INFO; + +// +// TYPEDEF_TEMP_SENSOR_SECTION - Macro that can be used to typedef the +// TEMP_SENSOR_SECTION structure, which provides information about all +// temperature sensors. +// +#define TYPEDEF_TEMP_SENSOR_SECTION(count) \ +typedef struct _TEMP_SENSOR_SECTION \ +{ \ + UINT8 byCount; \ + TEMP_SENSOR_INFO stSensor[count]; \ + \ +} TEMP_SENSOR_SECTION, *P_TEMP_SENSOR_SECTION + +// +// VOLT_SENSOR_INFO - Structure providing info for a voltage sensor. +// +typedef struct _VOLT_SENSOR_INFO +{ + UINT8 byDevice; // Device index + UINT8 byIndex; // Physical sensor index + UINT8 byUsage; // Usage indicator + +} VOLT_SENSOR_INFO, *P_VOLT_SENSOR_INFO; + +// +// TYPEDEF_VOLT_SENSOR_SECTION - Macro that can be used to typedef the +// VOLT_SENSOR_SECTION structure, which provides information about all +// voltage sensors. +// +#define TYPEDEF_VOLT_SENSOR_SECTION(count) \ +typedef struct _VOLT_SENSOR_SECTION \ +{ \ + UINT8 byCount; \ + VOLT_SENSOR_INFO stSensor[count]; \ + \ +} VOLT_SENSOR_SECTION, *P_VOLT_SENSOR_SECTION + +// +// FAN_SENSOR_INFO - Structure providing info for a fan speed sensor. +// +typedef struct _FAN_SENSOR_INFO +{ + UINT8 byDevice; // Device index + UINT8 byIndex; // Physical sensor index + UINT8 byUsage; // Usage indicator + UINT8 byType; // Fan type + UINT8 byController; // Associated Fan Controller + +} FAN_SENSOR_INFO, *P_FAN_SENSOR_INFO; + +// +// TYPEDEF_FAN_SENSOR_SECTION - Macro that can be used to typedef the +// FAN_SENSOR_SECTION structure, which provides information about all fan +// speed sensors. +// +#define TYPEDEF_FAN_SENSOR_SECTION(count) \ +typedef struct _FAN_SENSOR_SECTION \ +{ \ + UINT8 byCount; \ + FAN_SENSOR_INFO stSensor[count]; \ + \ +} FAN_SENSOR_SECTION, *P_FAN_SENSOR_SECTION + +// +// FAN_CONTROLLER_INFO - Structure providing info for a fan speed controller. +// +#define MAX_ASSOC_FANS 4 +#define ASSOC_UNUSED 0xFF + +typedef struct _FAN_CONTROLLER_INFO +{ + UINT8 byDevice; // Device index + UINT8 byIndex; // Physical Controller Index + UINT8 byUsage; // Usage Indicator + UINT8 byFan[MAX_ASSOC_FANS]; // Associated Fan Sensors + +} FAN_CONTROLLER_INFO, *P_FAN_CONTROLLER_INFO; + +// +// TYPEDEF_FAN_CONTROLLER_SECTION - Macro that can be used to typedef the +// FAN_CONTROLLER_SECTION structure, which provides information about all +// fan speed controllers. +// +#define TYPEDEF_FAN_CONTROLLER_SECTION(count) \ +typedef struct _FAN_CONTROLLER_SECTION \ +{ \ + UINT8 byCount; \ + FAN_CONTROLLER_INFO stController[count]; \ + \ +} FAN_CONTROLLER_SECTION, *P_FAN_CONTROLLER_SECTION + +// +// TYPEDEF_SENSOR_INFO_VAR - Macro that can be used to typedef the +// SENSOR_INFO_VAR structure, which provides information about all sensors +// and fan speed controllers. The other TYPEDEF macros must be invoked +// before using this one... +// +#define TYPEDEF_SENSOR_INFO_VAR \ +typedef struct _SENSOR_INFO_VAR \ +{ \ + TEMP_SENSOR_SECTION stTemps; \ + VOLT_SENSOR_SECTION stVolts; \ + FAN_SENSOR_SECTION stFans; \ + FAN_CONTROLLER_SECTION stCtrls; \ + \ +} SENSOR_INFO_VAR, *P_SENSOR_INFO_VAR + +#pragma pack() + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Guid/SetupVariable.h b/Vlv2TbltDevicePkg/Include/Guid/SetupVariable.h new file mode 100644 index 0000000000..eb0a1760b0 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Guid/SetupVariable.h @@ -0,0 +1,1351 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + + This program and the accompanying materials are licensed and made available under + + the terms and conditions of the BSD License that accompanies this distribution. + + The full text of the license may be found at + + http://opensource.org/licenses/bsd-license.php. + + + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +Module Name: + + SetupVariable.h + +Abstract: + + Driver configuration include file + + +--*/ + +#ifndef _SETUP_VARIABLE_H +#define _SETUP_VARIABLE_H + +// +// --------------------------------------------------------------------------- +// +// Driver Configuration +// +// --------------------------------------------------------------------------- +// + +// +// {EC87D643-EBA4-4bb5-A1E5-3F3E36B20DA9} +// +#define SYSTEM_CONFIGURATION_GUID\ + { \ + 0xec87d643, 0xeba4, 0x4bb5, 0xa1, 0xe5, 0x3f, 0x3e, 0x36, 0xb2, 0xd, 0xa9 \ + } + +#define ROOT_SECURITY_GUID\ + { \ + 0xd387d688, 0xeba4, 0x45b5, 0xa1, 0xe5, 0x3f, 0x3e, 0x36, 0xb2, 0xd, 0x37 \ + } + +// +// {6936B3BD-4350-46d9-8940-1FA20961AEB1} +// +#define SYSTEM_ROOT_MAIN_GUID\ + { \ + 0x6936b3bd, 0x4350, 0x46d9, 0x89, 0x40, 0x1f, 0xa2, 0x9, 0x61, 0xae, 0xb1 \ + } + +// +// {21FEE8DB-0D29-477e-B5A9-96EB343BA99C} +// +#define ADDITIONAL_SYSTEM_INFO_GUID\ + { \ + 0x21fee8db, 0xd29, 0x477e, 0xb5, 0xa9, 0x96, 0xeb, 0x34, 0x3b, 0xa9, 0x9c \ + } + +#define SETUP_GUID { 0xEC87D643, 0xEBA4, 0x4BB5, 0xA1, 0xE5, 0x3F, 0x3E, 0x36, 0xB2, 0x0D, 0xA9 } + +// {1B838190-4625-4ead-ABC9-CD5E6AF18FE0} +#define EFI_HII_EXPORT_DATABASE_GUID { 0x1b838190, 0x4625, 0x4ead, 0xab, 0xc9, 0xcd, 0x5e, 0x6a, 0xf1, 0x8f, 0xe0 } + +#define PASSWORD_MAX_SIZE 20 + +#define MAX_CUSTOM_VID_TABLE_STATES 6 +// +// Overclocking Source Defines +// +#define OVERCLOCK_SOURCE_BIOS 0 +#define OVERCLOCK_SOURCE_OS 1 + +#define PCH_PCIE_MAX_ROOT_PORTS 4 + +#pragma pack(1) + +// NOTE: When you add anything to this structure, +// you MUST add it to the very bottom!!!! +// You must make sure the structure size is able to divide by 32! +typedef struct { + + // + // Floppy + // + UINT8 Floppy; + UINT8 FloppyLockHide; + + UINT8 FloppyWriteProtect; + UINT8 FloppyWriteProtectLockHide; + + // + // System ports + // + UINT8 Serial; + UINT8 SerialLockHide; + + UINT8 Serial2; + UINT8 Serial2LockHide; + + UINT8 Parallel; + UINT8 ParallelLockHide; + + UINT8 ParallelMode; + UINT8 ParallelModeLockHide; + + UINT8 AllUsb; + UINT8 UsbPortsLockHide; + + UINT8 Usb2; + UINT8 Usb2LockHide; + + UINT8 UsbLegacy; + UINT8 UsbLegacyLockHide; + + UINT8 Audio; + UINT8 AudioLockHide; + + UINT8 Lan; + UINT8 LanLockHide; + + // + // Keyboard + // + UINT8 Numlock; + UINT8 NumlockLockHide; + + // + // ECIR + // + UINT8 ECIR; + UINT8 ECIRLockHide; + + // + // Power State + // + UINT8 PowerState; + UINT8 PowerStateLockHide; + + // + // Wake on RTC variables + // + UINT8 WakeOnRtcS5; + UINT8 WakeOnRtcS5LockHide; + UINT8 RTCWakeupDate; + UINT8 RTCWakeupDateLockHide; + UINT8 RTCWakeupTimeHour; + UINT8 RTCWakeupHourLockHide; + UINT8 RTCWakeupTimeMinute; + UINT8 RTCWakeupMinuteLockHide; + UINT8 RTCWakeupTimeSecond; + UINT8 RTCWakeupSecondLockHide; + + // + // Wake On Lan + // + UINT8 WakeOnLanS5; + UINT8 WakeOnLanS5LockHide; + + //Spread spectrum + UINT8 SpreadSpectrum; + + // + // Boot Order + // + UINT8 BootOrder[8]; + UINT8 BootOrderLockHide; + + // + // Hard Drive Boot Order + // + UINT8 HardDriveBootOrder[8]; + UINT8 HardDriveBootOrderLockHide; + + // + // CD Drive Boot Order + // + UINT8 CdDriveBootOrder[4]; + UINT8 CdDriveBootOrderLockHide; + + // + // FDD Drive Boot Order + // + UINT8 FddDriveBootOrder[4]; + UINT8 FddDriveBootOrderLockHide; + + // + // Drive Boot Order + // + UINT8 DriveBootOrder[16]; + UINT8 DriveBootOrderLockHide; + + // + // Boot Menu Type + // + UINT8 BootMenuType; + UINT8 BootMenuTypeLockHide; + + // + // Boot from Removable Devices + // + UINT8 BootFloppy; + UINT8 BootFloppyLockHide; + + // + // Boot from Optical Devices + // + UINT8 BootCd; + UINT8 BootCdLockHide; + + // + // Boot from Network + // + UINT8 BootNetwork; + UINT8 BootNetworkLockHide; + + // + // Boot USB + // + UINT8 BootUsb; + UINT8 BootUsbLockHide; + + // + // USB Zip Emulation Type + // + UINT8 UsbZipEmulation; + UINT8 UsbZipEmulationLockHide; + + // + // USB Devices Boot First in Boot Order + // + UINT8 UsbDevicesBootFirst; + UINT8 UsbDevicesBootFirstLockHide; + + // + // USB Boot Device SETUP Emulation + // + UINT8 UsbSetupDeviceEmulation; + UINT8 UsbSetupDeviceEmulationLockHide; + + // + // BIOS INT13 Emulation for USB Mass Devices + // + UINT8 UsbBIOSINT13DeviceEmulation; + UINT8 UsbBIOSINT13DeviceEmulationLockHide; + + // + // BIOS INT13 Emulation Size for USB Mass Devices + // + UINT16 UsbBIOSINT13DeviceEmulationSize; + UINT8 UsbBIOSINT13DeviceEmulationSizeLockHide; + + // + // Dummy place holder to prevent VFR compiler problem. + // + UINT16 DummyDataForVfrBug; // Don't change or use. + + // + // Language Select + // + UINT8 LanguageSelect; + + // + // SATA Type (Ide, Ahci, Raid) + // + UINT8 SataType; + UINT8 SataTypeLockHide; + UINT8 SataTestMode; + + // + // Fixed Disk Boot Sector (Fdbs) + // + UINT8 Fdbs; + UINT8 FdbsLockHide; + + // + // DisplaySetupPrompt + // + UINT8 DisplaySetupPrompt; + UINT8 DisplaySetupPromptLockHide; + + // + // ASF + // + UINT8 Asf; + UINT8 AsfLockHide; + + // + // Event Logging + // + UINT8 EventLogging; + UINT8 EventLoggingLockHide; + + // + // Clear Event Log + // + UINT8 ClearEvents; + UINT8 ClearEventsLockHide; + + // + // Expansion Card Text + // + UINT8 ExpansionCardText; + UINT8 ExpansionCardTextLockHide; + + // + // Video Adaptor + // + UINT8 PrimaryVideoAdaptor; + UINT8 PrimaryVideoAdaptorLockHide; + + // + // Chassis intrusion + // + UINT8 IntruderDetection; + UINT8 IntruderDetectionLockHide; + + // + // User Access Level + // + UINT8 UserPasswordLevel; + UINT8 UserPasswordLevelLockHide; + + // + // Maximum FSB Automatic/Disable + // + UINT8 MaxFsb; + UINT8 MaxFsbLockHide; + + // + // Hard Disk Pre-delay + // + UINT8 HddPredelay; + UINT8 HddPredelayLockHide; + + // + // S.M.A.R.T. Mode + // + UINT8 SmartMode; + UINT8 SmartModeLockHide; + + // + // ACPI Suspend State + // + UINT8 AcpiSuspendState; + UINT8 AcpiSuspendStateLockHide; + + // + // PCI Latency Timer + // + UINT8 PciLatency; + UINT8 PciLatencyLockHide; + + // + // Fan Control + // + UINT8 FanControl; + UINT8 FanControlLockHide; + + // + // CPU Fan Control + // + UINT8 CpuFanControl; + UINT8 CpuFanControlLockHide; + + // + // Lowest Fan Speed + // + UINT8 LowestFanSpeed; + UINT8 LowestFanSpeedLockHide; + + // + // Processor (CPU) + // + UINT8 CpuFlavor; + + UINT8 CpuidMaxValue; + UINT8 CpuidMaxValueLockHide; + + UINT8 ExecuteDisableBit; + UINT8 ExecuteDisableBitLockHide; + + // + // EIST or GV3 setup option + // + UINT8 ProcessorEistEnable; + UINT8 ProcessorEistEnableLockHide; + + // + // C1E Enable + // + UINT8 ProcessorC1eEnable; + UINT8 ProcessorC1eEnableLockHide; + + // + // Enabling CPU C-States of processor + // + UINT8 ProcessorCcxEnable; + UINT8 ProcessorCcxEnableLockHide; + + // + // Package C-State Limit + // + UINT8 PackageCState; + UINT8 PackageCStateLockHide; + + // + // Enable/Disable NHM C3(ACPI C2) report to OS + // + UINT8 OSC2Report; + UINT8 OSC2ReportLockHide; + + // + // Enable/Disable NHM C6(ACPI C3) report to OS + // + UINT8 C6Enable; + UINT8 C6EnableLockHide; + + // + // Enable/Disable NHM C7(ACPI C3) report to OS + // + UINT8 C7Enable; + UINT8 C7EnableLockHide; + + // + // EIST/PSD Function select option + // + UINT8 ProcessorEistPsdFunc; + UINT8 ProcessorEistPsdFuncLockHide; + + // + // + // + UINT8 CPU00; + UINT8 CPU01; + + // + // + // + UINT8 CPU02; + UINT8 CPU03; + + // + // + // + UINT8 CPU04; + UINT8 CPU05; + + // + // + // + UINT8 CPU06; + UINT8 CPU07; + + // + // + // + UINT8 CPU08; + UINT8 CPU09; + + // + // + // + UINT8 CPU10; + UINT8 CPU11; + + // + // + // + UINT8 CPU12; + UINT8 CPU13; + + // + // + // + UINT8 CPU14; + UINT8 CPU15; + + // + // + // + UINT8 CPU16; + UINT8 CPU17; + + // + // + // + UINT8 CPU18; + UINT8 CPU19; + + // + // + // + UINT8 CPU20; + UINT8 CPU21; + + // + // + // + UINT8 CPU22; + UINT8 CPU23; + + // + // + // + UINT8 CPU24; + UINT8 CPU25; + + // + // + // + UINT8 CPU26; + UINT8 CPU27; + + // + // + // + UINT8 CPU28; + UINT8 CPU29; + + // + // + // + UINT8 CPU30; + UINT8 CPU31; + + // + // + // + UINT8 CPU32; + UINT8 CPU33; + + // + // + // + UINT8 CPU34; + UINT8 CPU35; + + // + // + // + UINT8 CPU36; + UINT8 CPU37; + + // + // + // + UINT8 CPU38; + UINT8 CPU39; + + // + // + // + UINT16 CPU40; + UINT8 CPU41; + + // + // + // + UINT8 CPU42; + UINT8 CPU43; + + // + // + // + UINT16 CPU44; + UINT8 CPU45; + + // + // + // + UINT8 CPU46; + UINT8 CPU47; + + // + // + // + UINT8 CPU48; + UINT8 CPU49; + + // + // + // + UINT8 CPU50; + UINT8 CPU51; + + // + // + // + UINT8 CPU52; + UINT8 CPU53; + + // + // + // + UINT8 CPU54; + UINT8 CPU55; + + // + // + // + UINT8 CPU56; + UINT8 CPU57; + + // + // + // + UINT8 CPU58; + UINT8 CPU59; + + // + // + // + UINT8 CPU60; + UINT8 CPU61; + + // + // + // + UINT8 CPU62; + UINT8 CPU63; + + // + // + // + UINT8 CPU64; + UINT8 CPU65; + + // + // + // + UINT8 CPU66; + UINT8 CPU67; + + // + // + // + UINT16 CPU68; + UINT8 CPU69; + + // + // + // + UINT16 CPU70; + + // + // + // + UINT8 CPU71; + + // + // + // + UINT8 MEM00; + UINT8 MEM01; + + // + // + // + UINT8 MEM02; + UINT8 MEM03; + + UINT16 MEM04; + UINT8 MEM05; + + UINT8 MEM06; + UINT8 MEM07; + + UINT8 MEM08; + UINT8 MEM09; + + UINT8 MEM10; + UINT8 MEM11; + + UINT8 MEM12; + UINT8 MEM13; + + UINT8 MEM14; + UINT8 MEM15; + + UINT8 MEM16; + UINT8 MEM17; + + UINT16 MEM18; + UINT8 MEM19; + + UINT8 MEM20; + UINT8 MEM21; + + UINT8 MEM22; + UINT8 MEM23; + + UINT8 MEM24; + UINT8 MEM25; + + UINT8 MEM26; + UINT8 MEM27; + + UINT8 MEM28; + UINT8 MEM29; + + UINT8 MEM30; + UINT8 MEM31; + + UINT8 MEM32; + UINT8 MEM33; + + UINT8 MEM34; + UINT8 MEM35; + + // + // + // + UINT8 MEM36; + UINT8 MEM37; + UINT8 MEM38; + UINT8 MEM39; + + // + // + // + UINT8 MEM40; + UINT8 MEM41; + UINT8 MEM42; + UINT8 MEM43; + UINT8 MEM44; + UINT8 MEM45; + UINT8 MEM46; + UINT8 MEM47; + + + // + // Port 80 decode 0/1 - PCI/LPC + UINT8 Port80Route; + UINT8 Port80RouteLockHide; + + // + // ECC Event Logging + // + UINT8 EccEventLogging; + UINT8 EccEventLoggingLockHide; + + // + // TPM Enable/Disable + // + UINT8 ETpm; + + // + // TPM question 0 = Disabled, 1 = Enabled + // + UINT8 ETpmClear; + + // + // Secondary SATA Controller question 0 = Disabled, 1 = Enabled + // + UINT8 ExtSata; + UINT8 ExtSataLockHide; + + // + // Mode selection for Secondary SATA Controller (0=IDE, 1=RAID) + // + UINT8 ExtSataMode; + UINT8 ExtSataModeLockHide; + + // + // LT Technology 0/1 -> Disable/Enable + // + UINT8 LtTechnology; + UINT8 LtTechnologyLockHide; + + // + // HPET Support 0/1 -> Disable/Enable + // + UINT8 Hpet; + UINT8 HpetLockHide; + + // + // ICH Function Level Reset enable/disable + // + UINT8 FlrCapability; + UINT8 FlrCapabilityLockHide; + + // VT-d Option + UINT8 VTdSupport; + UINT8 VTdSupportLockHide; + + UINT8 InterruptRemap; + UINT8 InterruptRemapLockHide; + + UINT8 Isoc; + UINT8 IsocLockHide; + + UINT8 CoherencySupport; + UINT8 CoherencySupportLockHide; + + UINT8 ATS; + UINT8 ATSLockHide; + + UINT8 PassThroughDma; + UINT8 PassThroughDmaLockHide; + + // + // IGD option + // + UINT8 GraphicsDriverMemorySize; + UINT8 GraphicsDriverMemorySizeLockHide; + + + // + // Discrete SATA Type (Ide, Raid, Ahci) + // + UINT8 ExtSataMode2; + UINT8 ExtSataMode2LockHide; + + UINT8 ProcessorReserve00; + UINT8 ProcessorReserve01; + + // + // IGD Aperture Size question + // + UINT8 IgdApertureSize; + UINT8 IgdApertureSizeLockHide; + + // + // Boot Display Device + // + UINT8 BootDisplayDevice; + UINT8 BootDisplayDeviceLockHide; + + + // + // System fan speed duty cycle + // + UINT8 SystemFanDuty; + UINT8 SystemFanDutyLockHide; + + + // + // S3 state LED indicator + // + UINT8 S3StateIndicator; + UINT8 S3StateIndicatorLockHide; + + // + // S1 state LED indicator + // + UINT8 S1StateIndicator; + UINT8 S1StateIndicatorLockHide; + + // + // PS/2 Wake from S5 + // + UINT8 WakeOnS5Keyboard; + UINT8 WakeOnS5KeyboardLockHide; + + + // + // SATA Controller question 0 = Disabled, 1 = Enabled + // + UINT8 Sata; + UINT8 SataLockHide; + + // + // PS2 port + // + UINT8 PS2; + + // + // No VideoBeep + // + UINT8 NoVideoBeepEnable; + + // + // Integrated Graphics Device + // + UINT8 Igd; + + // + // Video Device select order + // + UINT8 VideoSelectOrder[8]; + + // Flash update sleep delay + UINT8 FlashSleepDelay; + UINT8 FlashSleepDelayLockHide; + + // + // Boot Display Device2 + // + UINT8 BootDisplayDevice2; + UINT8 BootDisplayDevice2LockHide; + + // + // Flat Panel + // + UINT8 EdpInterfaceType; + UINT8 EdpInterfaceTypeLockHide; + + UINT8 LvdsInterfaceType; + UINT8 LvdsInterfaceTypeLockHide; + + UINT8 ColorDepth; + UINT8 ColorDepthLockHide; + + UINT8 EdidConfiguration; + UINT8 EdidConfigurationLockHide; + + UINT8 PwmReserved; + UINT8 MaxInverterPWMLockHide; + + UINT8 PreDefinedEdidConfiguration; + UINT8 PreDefinedEdidConfigurationLockHide; + + UINT16 ScreenBrightnessResponseTime; + UINT8 ScreenBrightnessResponseTimeLockHide; + + UINT8 Serial3; + UINT8 Serial3LockHide; + + UINT8 Serial4; + UINT8 Serial4LockHide; + + UINT8 CurrentSetupProfile; + UINT8 CurrentSetupProfileLockHide; + + // + // FSC system Variable + // + UINT8 CPUFanUsage; + UINT8 CPUFanUsageLockHide; + UINT16 CPUUnderSpeedthreshold; + UINT8 CPUUnderSpeedthresholdLockHide; + UINT8 CPUFanControlMode; + UINT8 CPUFanControlModeLockHide; + UINT16 Voltage12UnderVolts; + UINT8 Voltage12UnderVoltsLockHide; + UINT16 Voltage12OverVolts; + UINT8 Voltage12OverVoltsLockHide; + UINT16 Voltage5UnderVolts; + UINT8 Voltage5UnderVoltsLockHide; + UINT16 Voltage5OverVolts; + UINT8 Voltage5OverVoltsLockHide; + UINT16 Voltage3p3UnderVolts; + UINT8 Voltage3p3UnderVoltsLockHide; + UINT16 Voltage3p3OverVolts; + UINT8 Voltage3p3OverVoltsLockHide; + UINT16 Voltage2p5UnderVolts; + UINT8 Voltage2p5UnderVoltsLockHide; + UINT16 Voltage2p5OverVolts; + UINT8 Voltage2p5OverVoltsLockHide; + UINT16 VoltageVccpUnderVolts; + UINT8 VoltageVccpUnderVoltsLockHide; + UINT16 VoltageVccpOverVolts; + UINT8 VoltageVccpOverVoltsLockHide; + UINT16 Voltage5BackupUnderVolts; + UINT8 Voltage5BackupUnderVoltsLockHide; + UINT16 Voltage5BackupOverVolts; + UINT8 Voltage5BackupOverVoltsLockHide; + UINT16 VS3p3StbyUnderVolt; + UINT8 VS3p3StbyUnderVoltLockHide; + UINT16 VS3p3StbyOverVolt; + UINT8 VS3p3StbyOverVoltLockHide; + UINT8 CPUFanMinDutyCycle; + UINT8 CPUFanMinDutyCycleLockHide; + UINT8 CPUFanMaxDutyCycle; + UINT8 CPUFanMaxDutyCycleLockHide; + UINT8 CPUFanOnDutyCycle; + UINT8 CPUFanOnDutyCycleLockHide; + UINT16 CpuOverTemp; + UINT8 CpuOverTempLockHide; + UINT16 CpuControlTemp; + UINT8 CpuControlTempLockHide; + UINT16 CpuAllOnTemp; + UINT8 CpuAllOnTempLockHide; + UINT8 CpuResponsiveness; + UINT8 CpuResponsivenessLockHide; + UINT8 CpuDamping; + UINT8 CpuDampingLockHide; + UINT16 PchOverTemp; + UINT8 PchOverTempLockHide; + UINT16 PchControlTemp; + UINT8 PchControlTempLockHide; + UINT16 PchAllOnTemp; + UINT8 PchAllOnTempLockHide; + UINT8 PchResponsiveness; + UINT8 PchResponsivenessLockHide; + UINT8 PchDamping; + UINT8 PchDampingLockHide; + UINT16 MemoryOverTemp; + UINT8 MemoryOverTempLockHide; + UINT16 MemoryControlTemp; + UINT8 MemoryControlTempLockHide; + UINT16 MemoryAllOnTemp; + UINT8 MemoryAllOnTempLockHide; + UINT8 MemoryResponsiveness; + UINT8 MemoryResponsivenessLockHide; + UINT8 MemoryDamping; + UINT8 MemoryDampingLockHide; + UINT16 VROverTemp; + UINT8 VROverTempLockHide; + UINT16 VRControlTemp; + UINT8 VRControlTempLockHide; + UINT16 VRAllOnTemp; + UINT8 VRAllOnTempLockHide; + UINT8 VRResponsiveness; + UINT8 VRResponsivenessLockHide; + UINT8 VRDamping; + UINT8 VRDampingLockHide; + + UINT8 LvdsBrightnessSteps; + UINT8 LvdsBrightnessStepsLockHide; + UINT8 EdpDataRate; + UINT8 EdpDataRateLockHide; + UINT16 LvdsPowerOnToBacklightEnableDelayTime; + UINT8 LvdsPowerOnToBacklightEnableDelayTimeLockHide; + UINT16 LvdsPowerOnDelayTime; + UINT8 LvdsPowerOnDelayTimeLockHide; + UINT16 LvdsBacklightOffToPowerDownDelayTime; + UINT8 LvdsBacklightOffToPowerDownDelayTimeLockHide; + UINT16 LvdsPowerDownDelayTime; + UINT8 LvdsPowerDownDelayTimeLockHide; + UINT16 LvdsPowerCycleDelayTime; + UINT8 LvdsPowerCycleDelayTimeLockHide; + + UINT8 IgdFlatPanel; + UINT8 IgdFlatPanelLockHide; + UINT8 Lan2; + UINT8 Lan2LockHide; + + UINT8 SwapMode; + UINT8 SwapModeLockHide; + + UINT8 Sata0HotPlugCap; + UINT8 Sata0HotPlugCapLockHide; + UINT8 Sata1HotPlugCap; + UINT8 Sata1HotPlugCapLockHide; + + UINT8 UsbCharging; + UINT8 UsbChargingLockHide; + + UINT8 Cstates; + UINT8 EnableC4; + UINT8 EnableC6; + + UINT8 FastBoot; + UINT8 EfiNetworkSupport; + UINT8 PxeRom; + + //Add for PpmPlatformPlicy + UINT8 PPM00; + UINT8 PPM01; + UINT8 PPM02; + UINT8 PPM03; + UINT8 PPM04; + UINT8 PPM05; + UINT8 PPM06; + UINT8 PPM07; + UINT8 PPM08; + UINT8 PPM09; + UINT8 PPM10; + UINT8 QuietBoot; + UINT8 LegacyUSBBooting; + + UINT8 PwmReserved02; + // + // Thermal Policy Values + // + UINT8 EnableDigitalThermalSensor; + UINT8 PassiveThermalTripPoint; + UINT8 PassiveTc1Value; + UINT8 PassiveTc2Value; + UINT8 PassiveTspValue; + UINT8 DisableActiveTripPoints; + UINT8 CriticalThermalTripPoint; + UINT8 IchPciExp[4]; + UINT8 DeepStandby; + UINT8 AlsEnable; + UINT8 IgdLcdIBia; + UINT8 LogBootTime; + + + UINT8 PcieRootPortIOApic[4]; + UINT8 IffsEnable; + UINT8 IffsOnS3RtcWake; + UINT8 IffsS3WakeTimerMin; + UINT8 IffsOnS3CritBattWake; + UINT8 IffsCritBattWakeThreshold; + UINT8 ScramblerSupport; + UINT8 SecureBoot; + UINT8 SecureBootCustomMode; + UINT8 SecureBootUserPhysicalPresent; + UINT8 CoreFreMultipSelect; + UINT8 MaxCState; + UINT8 PanelScaling; + UINT8 IgdLcdIGmchBlc; + UINT8 GfxBoost; + UINT8 IgdThermal; + UINT8 SEC00; + UINT8 SEC01; + UINT8 SEC02; + UINT8 SEC03; + UINT8 MeasuredBootEnable; + UINT8 UseProductKey; + //Image Signal Processor PCI Device Configuration + // + UINT8 ISPDevSel; + UINT8 ISPEn; + // Passwords + UINT16 UserPassword[PASSWORD_MAX_SIZE]; + UINT16 AdminPassword[PASSWORD_MAX_SIZE]; + UINT8 Tdt; + UINT8 Recovery; + UINT8 Suspend; + UINT8 TdtState; + UINT8 TdtEnrolled; + UINT8 PBAEnable; + + UINT8 HpetBootTime; + UINT8 UsbDebug; + UINT8 Lpe; + // + // LPSS Configuration + // + UINT8 LpssPciModeEnabled; + //Scc + UINT8 LpsseMMCEnabled; + UINT8 LpssSdioEnabled; + UINT8 LpssSdcardEnabled; + UINT8 LpssSdCardSDR25Enabled; + UINT8 LpssSdCardDDR50Enabled; + UINT8 LpssMipiHsi; + UINT8 LpsseMMC45Enabled; + UINT8 LpsseMMC45DDR50Enabled; + UINT8 LpsseMMC45HS200Enabled; + UINT8 LpsseMMC45RetuneTimerValue; + UINT8 eMMCBootMode; + + //LPSS2 + UINT8 LpssDma1Enabled; + UINT8 LpssI2C0Enabled; + UINT8 LpssI2C1Enabled; + UINT8 LpssI2C2Enabled; + UINT8 LpssI2C3Enabled; + UINT8 LpssI2C4Enabled; + UINT8 LpssI2C5Enabled; + UINT8 LpssI2C6Enabled; + //LPSS1 + UINT8 LpssDma0Enabled; + UINT8 LpssPwm0Enabled; + UINT8 LpssPwm1Enabled; + UINT8 LpssHsuart0Enabled; + UINT8 LpssHsuart1Enabled; + UINT8 LpssSpiEnabled; + UINT8 I2CTouchAd; + + UINT8 GTTSize; + // + // DVMT5.0 Graphic memory setting + // + UINT8 IgdDvmt50PreAlloc; + UINT8 IgdDvmt50TotalAlloc; + UINT8 IgdTurboEnabled; + + // + // Usb Config + // + UINT8 UsbAutoMode; // PCH controller Auto mode + UINT8 UsbXhciSupport; + UINT8 Hsic0; + UINT8 PchUsb30Mode; + UINT8 PchUsb30Streams; + UINT8 PchUsb20; + UINT8 PchUsbPerPortCtl; + UINT8 PchUsbPort[8]; + UINT8 PchUsbRmh; + UINT8 PchUsbOtg; + UINT8 PchUsbVbusOn; //OTG VBUS control + UINT8 PchFSAOn; //FSA control + UINT8 EhciPllCfgEnable; + + + //Gbe + UINT8 PcieRootPortSpeed[PCH_PCIE_MAX_ROOT_PORTS]; + UINT8 SlpLanLowDc; + + UINT8 ISCT00; + UINT8 ISCT01; + UINT8 ISCT02; + UINT8 ISCT03; + UINT8 ISCT04; + UINT8 ISCT05; + UINT8 ISCT06; + UINT8 ISCT07; + // + // Azalia Configuration + // + UINT8 PchAzalia; + UINT8 AzaliaVCiEnable; + UINT8 AzaliaDs; + UINT8 AzaliaPme; + UINT8 HdmiCodec; + + UINT8 UartInterface; + UINT8 PcuUart1; + //UINT8 PcuUart2;//for A0 + UINT8 StateAfterG3; + UINT8 EnableClockSpreadSpec; + UINT8 GraphicReserve00; + UINT8 GOPEnable; + UINT8 GOPBrightnessLevel; //Gop Brightness level + UINT8 PavpMode; + UINT8 SEC04; + UINT8 SEC05; + UINT8 SEC06; + UINT8 SEC07; + + UINT8 HdmiCodecPortB; + UINT8 HdmiCodecPortC; + UINT8 HdmiCodecPortD; + UINT8 LidStatus; + UINT8 Reserved00; + UINT8 Reserved01; + UINT16 Reserved02; + UINT16 Reserved03; + UINT16 Reserved04; + UINT16 Reserved05; + UINT16 Reserved06; + UINT16 Reserved07; + UINT16 Reserved08; + UINT16 Reserved09; + UINT16 Reserved0A; + UINT16 Reserved0B; + UINT16 Reserved0C; + UINT16 Reserved0D; + UINT8 Reserved0E; + UINT8 Reserved0F; + UINT32 Reserved10; + UINT32 Reserved11; + UINT32 Reserved12; + UINT32 Reserved13; + UINT32 Reserved14; + UINT8 Reserved15; + UINT8 Reserved16; + UINT8 Reserved17; + UINT8 Reserved18; + UINT8 Reserved19; + UINT8 Reserved1A; + UINT8 Reserved1B; + UINT8 Reserved1C; + UINT8 Reserved1D; + UINT8 Reserved1E; + UINT8 Reserved1F; + UINT8 Reserved20; + UINT8 PmicEnable; + UINT8 IdleReserve; + UINT8 TSEGSizeSel; + UINT8 ACPIMemDbg; + UINT8 ExISupport; + UINT8 BatteryChargingSolution; //0-non ULPMC 1-ULPMC + UINT8 PnpSettings; + UINT8 CfioPnpSettings; + UINT8 PchEhciDebug; + UINT8 CRIDSettings; + UINT8 ULPMCFWLock; + UINT8 SpiRwProtect; + UINT8 GraphicReserve02; + UINT8 PDMConfig; + UINT16 LmMemSize; + UINT8 PunitBIOSConfig; + UINT8 LpssSdioMode; + UINT8 ENDBG2; + UINT8 WittEnable; + UINT8 UtsEnable; + UINT8 TristateLpc; + UINT8 GraphicReserve05; + UINT8 UsbXhciLpmSupport; + UINT8 EnableAESNI; + UINT8 SecureErase; + + UINT8 MmioSize; + + + UINT8 SAR1; + + UINT8 DisableCodec262; + UINT8 ReservedO; + UINT8 PcieDynamicGating; // Need PMC enable it first from PMC 0x3_12 MCU 318. + + UINT8 MipiDsi; + + //Added flow control item for UART1 and UART2 + UINT8 LpssHsuart0FlowControlEnabled; + UINT8 LpssHsuart1FlowControlEnabled; + + UINT8 SdCardRemovable; // ACPI reporting MMC/SD media as: removable/non-removable + + UINT8 GpioWakeCapability; + +} SYSTEM_CONFIGURATION; +#pragma pack() + +#ifndef PLATFORM_SETUP_VARIABLE_NAME +#define PLATFORM_SETUP_VARIABLE_NAME L"Setup" +#endif + +#pragma pack(1) +typedef struct{ + // Passwords + UINT16 UserPassword[PASSWORD_MAX_SIZE]; + UINT16 AdminPassword[PASSWORD_MAX_SIZE]; + UINT16 DummyDataForVfrBug; // Don't change or use + +} SYSTEM_PASSWORDS; +#pragma pack() + +// +// #defines for Drive Presence +// +#define EFI_HDD_PRESENT 0x01 +#define EFI_HDD_NOT_PRESENT 0x00 +#define EFI_CD_PRESENT 0x02 +#define EFI_CD_NOT_PRESENT 0x00 + +#define EFI_HDD_WARNING_ON 0x01 +#define EFI_CD_WARNING_ON 0x02 +#define EFI_SMART_WARNING_ON 0x04 +#define EFI_HDD_WARNING_OFF 0x00 +#define EFI_CD_WARNING_OFF 0x00 +#define EFI_SMART_WARNING_OFF 0x00 + +#ifndef VFRCOMPILE +extern EFI_GUID gEfiSetupVariableGuid; +#endif + +#define SETUP_DATA SYSTEM_CONFIGURATION + +#endif // #ifndef _SETUP_VARIABLE diff --git a/Vlv2TbltDevicePkg/Include/Hpet.h b/Vlv2TbltDevicePkg/Include/Hpet.h new file mode 100644 index 0000000000..10ada915b1 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Hpet.h @@ -0,0 +1,45 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Mseg.h + +Abstract: + + This file describes the contents of the ACPI HEPT Table. + +--*/ + +#ifndef _HPET_H +#define _HPET_H + +// +// Statements that include other files +// +#include +#include +#include +#include + +// +// HPET Definitions +// +#define EFI_ACPI_HPET_TABLE_REVISION 0x1 +#define MAIN_COUNTER_MIN_PERIODIC_CLOCK_TICKS 0x80 //approx 1ms + +#define HPET_BASE_ADDRESS 0xFED00000 +#define EFI_ACPI_EVENT_TIMER_BLOCK_ID 0x8086A001 + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Library/BiosIdLib.h b/Vlv2TbltDevicePkg/Include/Library/BiosIdLib.h new file mode 100644 index 0000000000..aa20539570 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/BiosIdLib.h @@ -0,0 +1,109 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + BiosIdLib.h + +Abstract: + + BIOS ID library definitions. + + This library provides functions to get BIOS ID, VERSION, DATE and TIME + +--*/ + +#ifndef _BIOS_ID_LIB_H_ +#define _BIOS_ID_LIB_H_ + +// +// BIOS ID string format: +// +// $(BOARD_ID)$(BOARD_REV).$(OEM_ID).$(VERSION_MAJOR).$(BUILD_TYPE)$(VERSION_MINOR).YYMMDDHHMM +// +// Example: "TRFTCRB1.86C.0008.D03.0506081529" +// +#pragma pack(1) + +typedef struct { + CHAR16 BoardId[7]; // "TRFTCRB" + CHAR16 BoardRev; // "1" + CHAR16 Dot1; // "." + CHAR16 OemId[3]; // "86C" + CHAR16 Dot2; // "." + CHAR16 VersionMajor[4]; // "0008" + CHAR16 Dot3; // "." + CHAR16 BuildType; // "D" + CHAR16 VersionMinor[2]; // "03" + CHAR16 Dot4; // "." + CHAR16 TimeStamp[10]; // "YYMMDDHHMM" + CHAR16 NullTerminator; // 0x0000 +} BIOS_ID_STRING; + +#define MEM_IFWIVER_START 0x7E0000 +#define MEM_IFWIVER_LENGTH 0x1000 + +typedef struct _MANIFEST_OEM_DATA{ + UINT32 Signature; + unsigned char FillNull[0x39]; + UINT32 IFWIVersionLen; + unsigned char IFWIVersion[32]; +}MANIFEST_OEM_DATA; + +// +// A signature precedes the BIOS ID string in the FV to enable search by external tools. +// +typedef struct { + UINT8 Signature[8]; // "$IBIOSI$" + BIOS_ID_STRING BiosIdString; // "TRFTCRB1.86C.0008.D03.0506081529" +} BIOS_ID_IMAGE; + +#pragma pack() + +/** + This function returns BIOS ID by searching HOB or FV. + + @param[in] BiosIdImage The BIOS ID got from HOB or FV + + @retval EFI_SUCCESS All parameters were valid and BIOS ID has been got. + @retval EFI_NOT_FOUND BiosId image is not found, and no parameter will be modified. + @retval EFI_INVALID_PARAMETER The parameter is NULL. + +**/ +EFI_STATUS +GetBiosId ( + OUT BIOS_ID_IMAGE *BiosIdImage + ); + +/** + This function returns the Version & Release Date and Time by getting and converting + BIOS ID. + + @param[in] BiosVersion The Bios Version out of the conversion. + @param[in] BiosReleaseDate The Bios Release Date out of the conversion. + @param[in] BiosReleaseTime The Bios Release Time out of the conversion. + + @retval EFI_SUCCESS BIOS Version & Release Date and Time have been got successfully. + @retval EFI_NOT_FOUND BiosId image is not found, and no parameter will be modified. + @retval EFI_INVALID_PARAMETER All the parameters are NULL. + +**/ +EFI_STATUS +GetBiosVersionDateTime ( + OUT CHAR16 *BiosVersion, OPTIONAL + OUT CHAR16 *BiosReleaseDate, OPTIONAL + OUT CHAR16 *BiosReleaseTime OPTIONAL + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Library/CpuIA32.h b/Vlv2TbltDevicePkg/Include/Library/CpuIA32.h new file mode 100644 index 0000000000..b8c53c94b3 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/CpuIA32.h @@ -0,0 +1,350 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + CpuIA32.h + +Abstract: + +--*/ + +#ifndef _CPU_IA32_H +#define _CPU_IA32_H + +typedef struct { + UINT32 RegEax; + UINT32 RegEbx; + UINT32 RegEcx; + UINT32 RegEdx; +} EFI_CPUID_REGISTER; + +typedef struct { + UINT32 HeaderVersion; + UINT32 UpdateRevision; + UINT32 Date; + UINT32 ProcessorId; + UINT32 Checksum; + UINT32 LoaderRevision; + UINT32 ProcessorFlags; + UINT32 DataSize; + UINT32 TotalSize; + UINT8 Reserved[12]; +} EFI_CPU_MICROCODE_HEADER; + +typedef struct { + UINT32 ExtendedSignatureCount; + UINT32 ExtendedTableChecksum; + UINT8 Reserved[12]; +} EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER; + +typedef struct { + UINT32 ProcessorSignature; + UINT32 ProcessorFlag; + UINT32 ProcessorChecksum; +} EFI_CPU_MICROCODE_EXTENDED_TABLE; + +typedef struct { + UINT32 Stepping : 4; + UINT32 Model : 4; + UINT32 Family : 4; + UINT32 Type : 2; + UINT32 Reserved1 : 2; + UINT32 ExtendedModel : 4; + UINT32 ExtendedFamily : 8; + UINT32 Reserved2 : 4; +} EFI_CPU_VERSION; + +#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_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_MSR_IA32_PLATFORM_ID 0x17 +#define EFI_MSR_IA32_APIC_BASE 0x1B +#define EFI_MSR_EBC_HARD_POWERON 0x2A +#define EFI_MSR_EBC_SOFT_POWERON 0x2B +#define BINIT_DRIVER_DISABLE 0x40 +#define INTERNAL_MCERR_DISABLE 0x20 +#define INITIATOR_MCERR_DISABLE 0x10 +#define EFI_MSR_EBC_FREQUENCY_ID 0x2C +#define EFI_MSR_IA32_BIOS_UPDT_TRIG 0x79 +#define EFI_MSR_IA32_BIOS_SIGN_ID 0x8B +#define EFI_MSR_PSB_CLOCK_STATUS 0xCD +#define EFI_APIC_GLOBAL_ENABLE 0x800 +#define EFI_MSR_IA32_MISC_ENABLE 0x1A0 +#define LIMIT_CPUID_MAXVAL_ENABLE_BIT 0x00400000 +#define AUTOMATIC_THERMAL_CONTROL_ENABLE_BIT 0x00000008 +#define COMPATIBLE_FPU_OPCODE_ENABLE_BIT 0x00000004 +#define LOGICAL_PROCESSOR_PRIORITY_ENABLE_BIT 0x00000002 +#define FAST_STRING_ENABLE_BIT 0x00000001 + +#define EFI_CACHE_VARIABLE_MTRR_BASE 0x200 +#define EFI_CACHE_VARIABLE_MTRR_END 0x20F +#define EFI_CACHE_IA32_MTRR_DEF_TYPE 0x2FF +#define EFI_CACHE_MTRR_VALID 0x800 +#define EFI_CACHE_FIXED_MTRR_VALID 0x400 +#define EFI_CACHE_VALID_ADDRESS 0xFFFFFF000 +#define EFI_MSR_VALID_MASK 0xFFFFFFFFF +#define EFI_CACHE_VALID_EXTENDED_ADDRESS 0xFFFFFFFFFF000 +#define EFI_MSR_VALID_EXTENDED_MASK 0xFFFFFFFFFFFFF + +#define EFI_IA32_MTRR_FIX64K_00000 0x250 +#define EFI_IA32_MTRR_FIX16K_80000 0x258 +#define EFI_IA32_MTRR_FIX16K_A0000 0x259 +#define EFI_IA32_MTRR_FIX4K_C0000 0x268 +#define EFI_IA32_MTRR_FIX4K_C8000 0x269 +#define EFI_IA32_MTRR_FIX4K_D0000 0x26A +#define EFI_IA32_MTRR_FIX4K_D8000 0x26B +#define EFI_IA32_MTRR_FIX4K_E0000 0x26C +#define EFI_IA32_MTRR_FIX4K_E8000 0x26D +#define EFI_IA32_MTRR_FIX4K_F0000 0x26E +#define EFI_IA32_MTRR_FIX4K_F8000 0x26F + +#define EFI_IA32_MCG_CAP 0x179 +#define EFI_IA32_MCG_CTL 0x17B +#define EFI_IA32_MC0_CTL 0x400 +#define EFI_IA32_MC0_STATUS 0x401 + +#define EFI_IA32_PERF_STATUS 0x198 +#define EFI_IA32_PERF_CTL 0x199 + +#define EFI_CACHE_UNCACHEABLE 0 +#define EFI_CACHE_WRITECOMBINING 1 +#define EFI_CACHE_WRITETHROUGH 4 +#define EFI_CACHE_WRITEPROTECTED 5 +#define EFI_CACHE_WRITEBACK 6 + +// +// Combine f(FamilyId), m(Model), s(SteppingId) to a single 32 bit number +// +#define EfiMakeCpuVersion(f, m, s) \ + (((UINT32) (f) << 16) | ((UINT32) (m) << 8) | ((UINT32) (s))) + +/** + Halt the Cpu + + @param[in] None + + @retval None + +**/ +VOID +EFIAPI +EfiHalt ( + VOID + ); + +/** + Write back and invalidate the Cpu cache + + @param[in] None + + @retval None + +**/ +VOID +EFIAPI +EfiWbinvd ( + VOID + ); + +/** + Invalidate the Cpu cache + + @param[in] None + + @retval None + +**/ +VOID +EFIAPI +EfiInvd ( + VOID + ); + +/** + Get the Cpu info by excute the CPUID instruction + + @param[in] RegisterInEax The input value to put into register EAX + @param[in] Regs The Output value + + @retval None + +**/ +VOID +EFIAPI +EfiCpuid ( + IN UINT32 RegisterInEax, + OUT EFI_CPUID_REGISTER *Regs + ); + +/** + When RegisterInEax != 4, the functionality is the same as EfiCpuid. + When RegisterInEax == 4, the function return the deterministic cache + parameters by excuting the CPUID instruction. + + @param[in] RegisterInEax The input value to put into register EAX. + @param[in] CacheLevel The deterministic cache level. + @param[in] Regs The Output value. + + @retval None + +**/ +VOID +EFIAPI +EfiCpuidExt ( + IN UINT32 RegisterInEax, + IN UINT32 CacheLevel, + OUT EFI_CPUID_REGISTER *Regs + ); + +/** + Read Cpu MSR + + @param[in] Index The index value to select the register + + @retval Return the read data + +**/ +UINT64 +EFIAPI +EfiReadMsr ( + IN UINT32 Index + ); + +/** + Write Cpu MSR + + @param[in] Index The index value to select the register + @param[in] Value The value to write to the selected register + + @retval None + +**/ +VOID +EFIAPI +EfiWriteMsr ( + IN UINT32 Index, + IN UINT64 Value + ); + +/** + Read Time stamp + + @param[in] None + + @retval Return the read data + +**/ +UINT64 +EFIAPI +EfiReadTsc ( + VOID + ); + +/** + Writing back and invalidate the cache,then diable it + + @param[in] None + + @retval None + +**/ +VOID +EFIAPI +EfiDisableCache ( + VOID + ); + +/** + Invalidate the cache,then Enable it + + @param[in] None + + @retval None + +**/ +VOID +EFIAPI +EfiEnableCache ( + VOID + ); + +/** + Get Eflags + + @param[in] None + + @retval Return the Eflags value + +**/ +UINT32 +EFIAPI +EfiGetEflags ( + VOID + ); + +/** + Disable Interrupts + + @param[in] None + + @retval None + +**/ +VOID +EFIAPI +EfiDisableInterrupts ( + VOID + ); + +/** + Enable Interrupts + + @param[in] None + + @retval None + +**/ +VOID +EFIAPI +EfiEnableInterrupts ( + VOID + ); + +/** + Extract CPU detail version infomation + + @param[in] FamilyId FamilyId, including ExtendedFamilyId + @param[in] Model Model, including ExtendedModel + @param[in] SteppingId SteppingId + @param[in] Processor Processor + +**/ +VOID +EFIAPI +EfiCpuVersion ( + IN UINT16 *FamilyId, OPTIONAL + IN UINT8 *Model, OPTIONAL + IN UINT8 *SteppingId, OPTIONAL + IN UINT8 *Processor OPTIONAL + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Library/EfiRegTableLib.h b/Vlv2TbltDevicePkg/Include/Library/EfiRegTableLib.h new file mode 100644 index 0000000000..796c64c9a1 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/EfiRegTableLib.h @@ -0,0 +1,201 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + EfiRegTableLib.h + +Abstract: + + Definitions and macros for building register tables for chipset + initialization.. + + Components linking this lib must include CpuIo, PciRootBridgeIo, and + BootScriptSave protocols in their DPX. + + + +--*/ + +#ifndef EFI_REG_TABLE_H +#define EFI_REG_TABLE_H + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define OPCODE_BASE(OpCode) ((UINT8)((OpCode) & 0xFF)) +#define OPCODE_FLAGS(OpCode) ((UINT8)(((OpCode) >> 8) & 0xFF)) +#define OPCODE_EXTRA_DATA(OpCode) ((UINT16)((OpCode) >> 16)) + +// +// RegTable Base OpCodes +// +#define OP_TERMINATE_TABLE 0 +#define OP_MEM_WRITE 1 +#define OP_MEM_READ_MODIFY_WRITE 2 +#define OP_IO_WRITE 3 +#define OP_IO_READ_MODIFY_WRITE 4 +#define OP_PCI_WRITE 5 +#define OP_PCI_READ_MODIFY_WRITE 6 +#define OP_STALL 7 + +// +// RegTable OpCode Flags +// +#define OPCODE_FLAG_S3SAVE 1 + + +#define TERMINATE_TABLE { (UINT32) OP_TERMINATE_TABLE, (UINT32) 0, (UINT32) 0 } + + +// +// REG_TABLE_ENTRY_PCI_WRITE encodes the width in the upper bits of the OpCode +// as one of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH values +// +typedef struct { + UINT32 OpCode; + UINT32 PciAddress; + UINT32 Data; +} EFI_REG_TABLE_PCI_WRITE; + +#define PCI_WRITE(Bus, Dev, Fnc, Reg, Width, Data, S3Flag) \ + { \ + (UINT32) (OP_PCI_WRITE | ((S3Flag) << 8) | ((Width) << 16)), \ + (UINT32) (EFI_PCI_ADDRESS ((Bus), (Dev), (Fnc), (Reg))), \ + (UINT32) (Data), \ + (UINT32) (0) \ + } + +typedef struct { + UINT32 OpCode; + UINT32 MemAddress; + UINT32 Data; +} EFI_REG_TABLE_MEM_WRITE; + +typedef struct { + UINT32 OpCode; + UINT32 PciAddress; + UINT32 OrMask; + UINT32 AndMask; +} EFI_REG_TABLE_PCI_READ_MODIFY_WRITE; + +#define PCI_READ_MODIFY_WRITE(Bus, Dev, Fnc, Reg, Width, OrMask, AndMask, S3Flag) \ + { \ + (UINT32) (OP_PCI_READ_MODIFY_WRITE | ((S3Flag) << 8) | ((Width) << 16)), \ + (UINT32) (EFI_PCI_ADDRESS ((Bus), (Dev), (Fnc), (Reg))), \ + (UINT32) (OrMask), \ + (UINT32) (AndMask) \ + } + +typedef struct { + UINT32 OpCode; + UINT32 MemAddress; + UINT32 OrMask; + UINT32 AndMask; +} EFI_REG_TABLE_MEM_READ_MODIFY_WRITE; + +#define MEM_READ_MODIFY_WRITE(Address, Width, OrMask, AndMask, S3Flag) \ + { \ + (UINT32) (OP_MEM_READ_MODIFY_WRITE | ((S3Flag) << 8) | ((Width) << 16)), \ + (UINT32) (Address), \ + (UINT32) (OrMask), \ + (UINT32) (AndMask) \ + } + +typedef struct { + UINT32 OpCode; + UINT32 Field2; + UINT32 Field3; + UINT32 Field4; +} EFI_REG_TABLE_GENERIC; + +typedef union { + EFI_REG_TABLE_GENERIC Generic; + EFI_REG_TABLE_PCI_WRITE PciWrite; + EFI_REG_TABLE_PCI_READ_MODIFY_WRITE PciReadModifyWrite; + EFI_REG_TABLE_MEM_READ_MODIFY_WRITE MemReadModifyWrite; +} EFI_REG_TABLE; + +/** + Processes register table assuming which may contain PCI, IO, MEM, and STALL + entries. + + No parameter checking is done so the caller must be careful about omitting + values for PciRootBridgeIo or CpuIo parameters. If the regtable does + not contain any PCI accesses, it is safe to omit the PciRootBridgeIo (supply + NULL). If the regtable does not contain any IO or Mem entries, it is safe to + omit the CpuIo (supply NULL). + + The RegTableEntry parameter is not checked, but is required. + + gBS is assumed to have been defined and is used when processing stalls. + + The function processes each entry sequentially until an OP_TERMINATE_TABLE + entry is encountered. + + @param[in] RegTableEntry A pointer to the register table to process + + @param[in] PciRootBridgeIo A pointer to the instance of PciRootBridgeIo that is used + when processing PCI table entries + + @param[in] CpuIo A pointer to the instance of CpuIo that is used when processing IO and + MEM table entries + + @retval Nothing. + +**/ +VOID +ProcessRegTablePci ( + EFI_REG_TABLE * RegTableEntry, + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * PciRootBridgeIo, + EFI_CPU_IO_PROTOCOL * CpuIo + ); + +/** + Processes register table assuming which may contain IO, MEM, and STALL + entries, but must NOT contain any PCI entries. Any PCI entries cause an + ASSERT in a DEBUG build and are skipped in a free build. + + No parameter checking is done. Both RegTableEntry and CpuIo parameters are + required. + + gBS is assumed to have been defined and is used when processing stalls. + + The function processes each entry sequentially until an OP_TERMINATE_TABLE + entry is encountered. + + @param[in] RegTableEntry - A pointer to the register table to process + + @param[in] CpuIo - A pointer to the instance of CpuIo that is used when processing IO and + MEM table entries + + @retval Nothing. + +**/ +VOID +ProcessRegTableCpu ( + EFI_REG_TABLE * RegTableEntry, + EFI_CPU_IO_PROTOCOL * CpuIo + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Library/Esrt.h b/Vlv2TbltDevicePkg/Include/Library/Esrt.h new file mode 100644 index 0000000000..06977b640a --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/Esrt.h @@ -0,0 +1,79 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Esrt.h + +Abstract: + +--*/ + +#ifndef _DFU_ESRT_H_ +#define _DFU_ESRT_H_ + +typedef struct { + EFI_GUID FwClass; + UINT32 FwType; + UINT32 FwVersion; + UINT32 FwLstCompatVersion; + UINT32 CapsuleFlags; + UINT32 LastAttemptVersion; + UINT32 LastAttemptStatus; +} FW_RES_ENTRY; + +typedef struct { + UINT32 NumEntries; + FW_RES_ENTRY FwEntries[256]; +} FW_RES_ENTRY_LIST; + + +typedef struct { + UINT32 FwResourceCount; + UINT32 FwResourceMax; + UINT64 FwResourceVersion; +} EFI_SYSTEM_RESOURCE_TABLE; + + +typedef +EFI_STATUS +(EFIAPI *ESRT_POPULATE_TABLE) ( +); + +typedef +EFI_STATUS +(EFIAPI *ESRT_UPDATE_TABLE_ENTRY_BY_GUID) ( + IN EFI_GUID FwEntryGuid, + IN FW_RES_ENTRY *FwEntry +); + +typedef +EFI_STATUS +(EFIAPI *ESRT_GET_FW_ENTRY_BY_GUID) ( + IN EFI_GUID FwEntryGuid, + OUT FW_RES_ENTRY *FwEntry +); + + +#pragma pack() + +typedef struct _ESRT_OPERATION_PROTOCOL { + ESRT_POPULATE_TABLE EsrtPopulateTable; + ESRT_UPDATE_TABLE_ENTRY_BY_GUID EsrtUpdateTableEntryByGuid; + ESRT_GET_FW_ENTRY_BY_GUID EsrtGetFwEntryByGuid; +} ESRT_OPERATION_PROTOCOL; + +extern EFI_GUID gEfiEsrtOperationProtocolGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Library/Fd.h b/Vlv2TbltDevicePkg/Include/Library/Fd.h new file mode 100644 index 0000000000..20c70527d8 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/Fd.h @@ -0,0 +1,269 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +Module Name: + + Fd.h + +Abstract: + + EFI Intel82802AB/82802AC Firmware Hub. + + +--*/ + + +// +// Supported SPI devices +// + +// +// MFG and Device code +// +#define SST_25LF040A 0x0044BF +#define SST_25LF040 0x0040BF +#define SST_25LF080A 0x0080BF +#define SST_25VF080B 0x008EBF +#define SST_25VF016B 0x0041BF +#define SST_25VF032B 0x004ABF + +#define PMC_25LV040 0x007E9D + +#define ATMEL_26DF041 0x00441F +#define Atmel_AT26F004 0x00041F +#define Atmel_AT26DF081A 0x01451F +#define Atmel_AT25DF161 0x02461F +#define Atmel_AT26DF161 0x00461F +#define Atmel_AT25DF641 0x00481F +#define Atmel_AT26DF321 0x00471F + +#define Macronix_MX25L8005 0x1420C2 +#define Macronix_MX25L1605A 0x1520C2 +#define Macronix_MX25L3205D 0x1620C2 + +#define STMicro_M25PE80 0x148020 + +#define Winbond_W25X40 0x1330EF +#define Winbond_W25X80 0x1430EF +#define Winbond_W25Q80 0x1440EF + +#define Winbond_W25X16 0x1540EF // W25Q16 +#define Winbond_W25X32 0x1630EF + +// +// NOTE: Assuming that 8Mbit flash will only contain a 4Mbit binary. +// Treating 4Mbit and 8Mbit devices the same. +// + +// +// BIOS Base Address +// +#define BIOS_BASE_ADDRESS_4M 0xFFF80000 +#define BIOS_BASE_ADDRESS_8M 0xFFF00000 +#define BIOS_BASE_ADDRESS_16M 0xFFE00000 + +// +// block and sector sizes +// +#define SECTOR_SIZE_256BYTE 0x100 // 256byte page size +#define SECTOR_SIZE_4KB 0x1000 // 4kBytes sector size +#define BLOCK_SIZE_32KB 0x00008000 // 32Kbytes block size +#define MAX_FLASH_SIZE 0x00400000 // 32Mbit (Note that this can also be used for the 4Mbit & 8Mbit) + +// +// Flash commands +// +#define SPI_SST25LF_COMMAND_WRITE 0x02 +#define SPI_SST25LF_COMMAND_READ 0x03 +#define SPI_SST25LF_COMMAND_ERASE 0x20 +#define SPI_SST25LF_COMMAND_WRITE_DISABLE 0x04 +#define SPI_SST25LF_COMMAND_READ_STATUS 0x05 +#define SPI_SST25LF_COMMAND_WRITE_ENABLE 0x06 +#define SPI_SST25LF_COMMAND_READ_ID 0xAB +#define SPI_SST25LF_COMMAND_WRITE_S_EN 0x50 +#define SPI_SST25LF_COMMAND_WRITE_S 0x01 + +#define SPI_PMC25LV_COMMAND_WRITE 0x02 +#define SPI_PMC25LV_COMMAND_READ 0x03 +#define SPI_PMC25LV_COMMAND_ERASE 0xD7 +#define SPI_PMC25LV_COMMAND_WRITE_DISABLE 0x04 +#define SPI_PMC25LV_COMMAND_READ_STATUS 0x05 +#define SPI_PMC25LV_COMMAND_WRITE_ENABLE 0x06 +#define SPI_PMC25LV_COMMAND_READ_ID 0xAB +#define SPI_PMC25LV_COMMAND_WRITE_S_EN 0x06 +#define SPI_PMC25LV_COMMAND_WRITE_S 0x01 + +#define SPI_AT26DF_COMMAND_WRITE 0x02 +#define SPI_AT26DF_COMMAND_READ 0x03 +#define SPI_AT26DF_COMMAND_ERASE 0x20 +#define SPI_AT26DF_COMMAND_WRITE_DISABLE 0x00 +#define SPI_AT26DF_COMMAND_READ_STATUS 0x05 +#define SPI_AT26DF_COMMAND_WRITE_ENABLE 0x00 +#define SPI_AT26DF_COMMAND_READ_ID 0x9F +#define SPI_AT26DF_COMMAND_WRITE_S_EN 0x00 +#define SPI_AT26DF_COMMAND_WRITE_S 0x00 + +#define SPI_AT26F_COMMAND_WRITE 0x02 +#define SPI_AT26F_COMMAND_READ 0x03 +#define SPI_AT26F_COMMAND_ERASE 0x20 +#define SPI_AT26F_COMMAND_WRITE_DISABLE 0x04 +#define SPI_AT26F_COMMAND_READ_STATUS 0x05 +#define SPI_AT26F_COMMAND_WRITE_ENABLE 0x06 +#define SPI_AT26F_COMMAND_JEDEC_ID 0x9F +#define SPI_AT26F_COMMAND_WRITE_S_EN 0x00 +#define SPI_AT26F_COMMAND_WRITE_S 0x01 +#define SPI_AT26F_COMMAND_WRITE_UNPROTECT 0x39 + +#define SPI_SST25VF_COMMAND_WRITE 0x02 +#define SPI_SST25VF_COMMAND_READ 0x03 +#define SPI_SST25VF_COMMAND_ERASE 0x20 +#define SPI_SST25VF_COMMAND_WRITE_DISABLE 0x04 +#define SPI_SST25VF_COMMAND_READ_STATUS 0x05 +#define SPI_SST25VF_COMMAND_WRITE_ENABLE 0x06 +#define SPI_SST25VF_COMMAND_READ_ID 0xAB +#define SPI_SST25VF_COMMAND_JEDEC_ID 0x9F +#define SPI_SST25VF_COMMAND_WRITE_S_EN 0x50 +#define SPI_SST25VF_COMMAND_WRITE_S 0x01 + +#define SPI_STM25PE_COMMAND_WRITE 0x02 +#define SPI_STM25PE_COMMAND_READ 0x03 +#define SPI_STM25PE_COMMAND_ERASE 0xDB +#define SPI_STM25PE_COMMAND_WRITE_DISABLE 0x04 +#define SPI_STM25PE_COMMAND_READ_STATUS 0x05 +#define SPI_STM25PE_COMMAND_WRITE_ENABLE 0x06 +#define SPI_STM25PE_COMMAND_JEDEC_ID 0x9F + +#define SPI_WinbondW25X_COMMAND_WRITE_S 0x01 +#define SPI_WinbondW25X_COMMAND_WRITE 0x02 +#define SPI_WinbondW25X_COMMAND_READ 0x03 +#define SPI_WinbondW25X_COMMAND_READ_STATUS 0x05 +#define SPI_WinbondW25X_COMMAND_ERASE_S 0x20 +#define SPI_WinbondW25X_COMMAND_WRITE_ENABLE 0x06 +#define SPI_WinbondW25X_COMMAND_JEDEC_ID 0x9F + +// +// SPI default opcode slots +// +#define SPI_OPCODE_WRITE_INDEX 0 +#define SPI_OPCODE_READ_INDEX 1 +#define SPI_OPCODE_ERASE_INDEX 2 +#define SPI_OPCODE_READ_S_INDEX 3 +#define SPI_OPCODE_READ_ID_INDEX 4 +#define SPI_OPCODE_WRITE_S_INDEX 6 +#define SPI_OPCODE_WRITE_UNPROTECT_INDEX 7 + +#define SPI_PREFIX_WRITE_S_EN 1 +#define SPI_PREFIX_WRITE_EN 0 + +// +// Atmel AT26F00x +// +#define B_AT26F_STS_REG_SPRL 0x80 +#define B_AT26F_STS_REG_SWP 0x0C + +// +// Block lock bit definitions: +// +#define READ_LOCK 0x04 +#define LOCK_DOWN 0x02 +#define WRITE_LOCK 0x01 +#define FULL_ACCESS 0x00 + +// +// Function Prototypes +// +EFI_STATUS +FlashGetNextBlock ( + IN UINTN* Key, + OUT EFI_PHYSICAL_ADDRESS* BlockAddress, + OUT UINTN* BlockSize + ); + +EFI_STATUS +FlashGetSize ( + OUT UINTN* Size + ); + +EFI_STATUS +FlashGetUniformBlockSize ( + OUT UINTN* Size + ); + +EFI_STATUS +FlashEraseWithNoTopSwapping ( + IN UINT8 *BaseAddress, + IN UINTN NumBytes + ); + +EFI_STATUS +FlashErase ( + IN UINT8 *BaseAddress, + IN UINTN NumBytes + ); + +EFI_STATUS +FlashWriteWithNoTopSwapping ( + IN UINT8* DstBufferPtr, + IN UINT8* SrcBufferPtr, + IN UINTN NumBytes + ); + +EFI_STATUS +FlashWrite ( + IN UINT8 *DstBufferPtr, + IN UINT8 *SrcBufferPtr, + IN UINTN NumBytes + ); + +EFI_STATUS +FlashReadWithNoTopSwapping ( + IN UINT8 *BaseAddress, + IN UINT8 *DstBufferPtr, + IN UINTN NumBytes + ); + +EFI_STATUS +FlashRead ( + IN UINT8 *BaseAddress, + IN UINT8 *DstBufferPtr, + IN UINTN NumBytes + ); + +EFI_STATUS +FlashLockWithNoTopSwapping ( + IN UINT8* BaseAddress, + IN UINTN NumBytes, + IN UINT8 LockState + ); + +EFI_STATUS +FlashLock( + IN UINT8 *BaseAddress, + IN UINTN NumBytes, + IN UINT8 LockState + ); + +EFI_STATUS +CheckIfErased( + IN UINT8 *DstBufferPtr, + IN UINTN NumBytes + ); + +EFI_STATUS +CheckIfFlashIsReadyForWrite ( + IN UINT8 *DstBufferPtr, + IN UINT8 *SrcBufferPtr, + IN UINTN NumBytes + ); diff --git a/Vlv2TbltDevicePkg/Include/Library/FlashDeviceLib.h b/Vlv2TbltDevicePkg/Include/Library/FlashDeviceLib.h new file mode 100644 index 0000000000..bddc1f89b3 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/FlashDeviceLib.h @@ -0,0 +1,127 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + Flash device library class header file. + + Flash Device Library common type, MACRO and API definition. The basic idea for + this library is to provide API to abstract the different between flash + technology (SPI, FWH etc..), flash controller (SPI host controller on + ICH, MMIO type access for FWH), flash chip (programming command, method + of status checking). This library class can be consumed by drivers or applications + such as Firmware Volume Block driver, Flash Update application. These driver + can be written in a generic manner so that they are more easy to be + ported to other platforms. + + This library can be build on a set of APIs which can touch flash controller, flash + chip directly for a platform with simple flash device configuration. + + For a platform with complex flash device configuration, this library can be built + on the Flash Device Operate Library. Please see the header file for that library + class for detailed usage. + +**/ + +#ifndef __FLASHDEVICE_LIB_H__ +#define __FLASHDEVICE_LIB_H__ + +/** + Read NumBytes bytes of data from the address specified by + PAddress into Buffer. + + @param[in] PAddress The starting physical address of the read. + @param[in,out] NumBytes On input, the number of bytes to read. On output, the number + of bytes actually read. + @param[out] Buffer The destination data buffer for the read. + + @retval EFI_SUCCESS. Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +LibFvbFlashDeviceRead ( + IN UINTN PAddress, + IN OUT UINTN *NumBytes, + OUT UINT8 *Buffer + ); + +/** + Write NumBytes bytes of data from Buffer to the address specified by + PAddresss. + + @param[in] PAddress The starting physical address of the write. + @param[in,out] NumBytes On input, the number of bytes to write. On output, + the actual number of bytes written. + @param[in] Buffer The source data buffer for the write. + + @retval EFI_SUCCESS. Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +LibFvbFlashDeviceWrite ( + IN UINTN PAddress, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + +/** + Erase the block staring at PAddress. + + @param[in] PAddress The starting physical address of the region to be erased. + @param[in] LbaLength The length of the region to be erased. This parameter is necessary + as the physical block size on a flash device could be different than + the logical block size of Firmware Volume Block protocol. Erase on + flash chip is always performed block by block. Therefore, the ERASE + operation to a logical block is converted a number of ERASE operation + (or a partial erase) on the hardware. + + @retval EFI_SUCCESS. Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +LibFvbFlashDeviceBlockErase ( + IN UINTN PAddress, + IN UINTN LbaLength +); + +/** + Lock or unlock the block staring at PAddress. + + @param[in] PAddress The starting physical address of region to be (un)locked. + @param[in] LbaLength The length of the region to be (un)locked. This parameter is necessary + as the physical block size on a flash device could be different than + the logical block size of Firmware Volume Block protocol. (Un)Lock on + flash chip is always performed block by block. Therefore, the (Un)Lock + operation to a logical block is converted a number of (Un)Lock operation + (or a partial erase) on the hardware. + @param[in] Lock TRUE to lock. FALSE to unlock. + + @retval EFI_SUCCESS. Opertion is successful. + +**/ +EFI_STATUS +EFIAPI +LibFvbFlashDeviceBlockLock ( + IN UINTN PAddress, + IN UINTN LbaLength, + IN BOOLEAN Lock +); + +#endif + + diff --git a/Vlv2TbltDevicePkg/Include/Library/I2cMmioConfigLib.h b/Vlv2TbltDevicePkg/Include/Library/I2cMmioConfigLib.h new file mode 100644 index 0000000000..b1f91471f0 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/I2cMmioConfigLib.h @@ -0,0 +1,28 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef __MMIO_CONFIG_LIB_H__ +#define __MMIO_CONFIG_LIB_H__ + +#include + +/// +/// Declare the memory mapped I/O devices assocaited with the +/// board. +/// +extern CONST EFI_MMIO_DEVICE_PROTOCOL gMmioDeviceList [ ]; +extern CONST UINTN gMmioDeviceCount; + +#endif // __MMIO_CONFIG_LIB_H__ diff --git a/Vlv2TbltDevicePkg/Include/Library/I2cPort_platform.h b/Vlv2TbltDevicePkg/Include/Library/I2cPort_platform.h new file mode 100644 index 0000000000..f52352f812 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/I2cPort_platform.h @@ -0,0 +1,31 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef _I2C_PORT_H +#define _I2C_PORT_H + +// +// Types +// + +// +// Context passed from platform (board) layer to the I2C port driver. +// +typedef struct { + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT32 InputFrequencyHertz; +} I2C_PIO_PLATFORM_CONTEXT; + +#endif // _I2C_PORT_A0_H diff --git a/Vlv2TbltDevicePkg/Include/Library/PlatformFsaLib.h b/Vlv2TbltDevicePkg/Include/Library/PlatformFsaLib.h new file mode 100644 index 0000000000..3ff3fb1852 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/PlatformFsaLib.h @@ -0,0 +1,55 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +--*/ + +#ifndef _FSA_LIB_H +#define _FSA_LIB_H +#include +#include + +#define FSA_REG_DEVID 0x1 +#define FSA_REG_CTRL 0x2 +#define FSA_REG_INTR 0x3 +#define FSA_REG_INTR_MSK 0x5 +#define FSA_REG_RESISTOR_CODE 0x7 +#define FSA_REG_TIMING_SET 0x8 +#define FSA_REG_STATUS 0x9 +#define FSA_REG_DEV_TYPE 0xA +#define FSA_REG_DAC_SAR 0xB +#define FSA_REG_MANUAL_SW 0x13 +#define FSA_REG_MANUAL_CHG_CTRL 0x14 + +extern +EFI_STATUS +EFIAPI +FsaUsbDeviceMode ( + VOID +); + + +extern +EFI_STATUS +EFIAPI +DisableFsaTimerHandler ( + VOID +); + +extern +EFI_STATUS +EFIAPI +FSAInit ( + IN UINT32 FFRDVer +); + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Library/PlatformFspLib.h b/Vlv2TbltDevicePkg/Include/Library/PlatformFspLib.h new file mode 100644 index 0000000000..2352514090 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/PlatformFspLib.h @@ -0,0 +1,28 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +--*/ + +#ifndef _PLATFORM_FSP_LIB_H +#define _PLATFORM_FSP_LIB_H +#include +#include + +extern +EFI_STATUS +PlatformHobCreateFromFsp ( + IN CONST EFI_PEI_SERVICES **PeiServices, + VOID *HobList + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Library/SpiFlash.H b/Vlv2TbltDevicePkg/Include/Library/SpiFlash.H new file mode 100644 index 0000000000..9d1e898fed --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/SpiFlash.H @@ -0,0 +1,244 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SPIFlash_H_ +#define _SPIFlash_H_ + +#include + +//EFI_STATUS SpiFlashLock(BOOLEAN Lock); +//EFI_STATUS SpiFlashInit(void); + +typedef enum { + EnumSpiFlashW25Q64, + EnumSpiFlashAT25DF321A, + EnumSpiFlashAT26DF321, + EnumSpiFlashAT25DF641, + EnumSpiFlashW25Q16, + EnumSpiFlashW25Q32, + EnumSpiFlashW25X32, + EnumSpiFlashW25X64, + EnumSpiFlashW25Q128, + EnumSpiFlashMX25L16, + EnumSpiFlashMX25L32, + EnumSpiFlashMX25L64, + EnumSpiFlashMX25L128, + EnumSpiFlashMX25U6435F, + EnumSpiFlashSST25VF016B, + EnumSpiFlashSST25VF064C, + EnumSpiFlashN25Q064, + EnumSpiFlashM25PX16, + EnumSpiFlashN25Q032, + EnumSpiFlashM25PX32, + EnumSpiFlashM25PX64, + EnumSpiFlashN25Q128, + EnumSpiFlashEN25Q16, + EnumSpiFlashEN25Q32, + EnumSpiFlashEN25Q64, + EnumSpiFlashEN25Q128, + EnumSpiFlashA25L016, + EnumSpiFlashMax +} SPI_FLASH_TYPES_SUPPORTED; + +// +// Serial Flash VendorId and DeviceId +// +#define SF_VENDOR_ID_ATMEL 0x1F +#define SF_DEVICE_ID0_AT26DF321 0x47 +#define SF_DEVICE_ID1_AT26DF321 0x00 +#define SF_DEVICE_ID0_AT25DF321A 0x47 +#define SF_DEVICE_ID1_AT25DF321A 0x01 +#define SF_DEVICE_ID0_AT25DF641 0x48 +#define SF_DEVICE_ID1_AT25DF641 0x00 + +#define SF_VENDOR_ID_WINBOND 0xEF +#define SF_DEVICE_ID0_W25XXX 0x30 +#define SF_DEVICE_ID1_W25X32 0x16 +#define SF_DEVICE_ID1_W25X64 0x17 +#define SF_DEVICE_ID0_W25QXX 0x60 +#define SF_DEVICE_ID1_W25Q16 0x15 +#define SF_DEVICE_ID1_W25Q32 0x16 +#define SF_DEVICE_ID1_W25Q64 0x17 +#define SF_DEVICE_ID1_W25Q128 0x18 + +#define SF_VENDOR_ID_MACRONIX 0xC2 +#define SF_DEVICE_ID0_MX25LXX 0x20 +#define SF_DEVICE_ID1_MX25L16 0x15 +#define SF_DEVICE_ID1_MX25L32 0x16 +#define SF_DEVICE_ID1_MX25L64 0x17 +#define SF_DEVICE_ID1_MX25L128 0x18 +#define SF_DEVICE_ID0_MX25UXX 0x25 +#define SF_DEVICE_ID1_MX25U6435F 0x37 + +#define SF_VENDOR_ID_NUMONYX 0x20 +#define SF_DEVICE_ID0_N25Q064 0xBB +#define SF_DEVICE_ID1_N25Q064 0x17 +#define SF_DEVICE_ID0_M25PXXX 0x71 +#define SF_DEVICE_ID0_N25QXXX 0xBA +#define SF_DEVICE_ID1_M25PX16 0x15 +#define SF_DEVICE_ID1_N25Q032 0x16 +#define SF_DEVICE_ID1_M25PX32 0x16 +#define SF_DEVICE_ID1_M25PX64 0x17 +#define SF_DEVICE_ID1_N25Q128 0x18 + +#define SF_VENDOR_ID_SST 0xBF +#define SF_DEVICE_ID0_SST25VF0XXX 0x25 +#define SF_DEVICE_ID1_SST25VF016B 0x41 +#define SF_DEVICE_ID1_SST25VF064C 0x4B + +#define SF_VENDOR_ID_EON 0x1C +#define SF_DEVICE_ID0_EN25QXX 0x30 +#define SF_DEVICE_ID1_EN25Q16 0x15 +#define SF_DEVICE_ID1_EN25Q32 0x16 +#define SF_DEVICE_ID1_EN25Q64 0x17 +#define SF_DEVICE_ID1_EN25Q128 0x18 + +#define SF_VENDOR_ID_AMIC 0x37 +#define SF_DEVICE_ID0_A25L016 0x30 +#define SF_DEVICE_ID1_A25L016 0x15 + +#define ATMEL_AT26DF321_SIZE 0x00400000 +#define ATMEL_AT25DF321A_SIZE 0x00400000 +#define ATMEL_AT25DF641_SIZE 0x00800000 +#define WINBOND_W25X32_SIZE 0x00400000 +#define WINBOND_W25X64_SIZE 0x00800000 +#define WINBOND_W25Q16_SIZE 0x00200000 +#define WINBOND_W25Q32_SIZE 0x00400000 +#define WINBOND_W25Q64_SIZE 0x00800000 +#define WINBOND_W25Q128_SIZE 0x01000000 +#define SST_SST25VF016B_SIZE 0x00200000 +#define SST_SST25VF064C_SIZE 0x00800000 +#define MACRONIX_MX25L16_SIZE 0x00200000 +#define MACRONIX_MX25L32_SIZE 0x00400000 +#define MACRONIX_MX25L64_SIZE 0x00800000 +#define MACRONIX_MX25U64_SIZE 0x00800000 +#define MACRONIX_MX25L128_SIZE 0x01000000 +#define NUMONYX_M25PX16_SIZE 0x00400000 +#define NUMONYX_N25Q032_SIZE 0x00400000 +#define NUMONYX_M25PX32_SIZE 0x00400000 +#define NUMONYX_M25PX64_SIZE 0x00800000 +#define NUMONYX_N25Q064_SIZE 0x00800000 +#define NUMONYX_N25Q128_SIZE 0x01000000 +#define EON_EN25Q16_SIZE 0x00200000 +#define EON_EN25Q32_SIZE 0x00400000 +#define EON_EN25Q64_SIZE 0x00800000 +#define EON_EN25Q128_SIZE 0x01000000 +#define AMIC_A25L16_SIZE 0x00200000 + +#define SF_VENDOR_ID_SST 0xBF +#define SF_DEVICE_ID0_25LF080A 0x25 +#define SF_DEVICE_ID1_25LF080A 0x8E +#define SF_DEVICE_ID0_25VF016B 0x25 +#define SF_DEVICE_ID1_25VF016B 0x41 + +#define SF_VENDOR_ID_ATMEL 0x1F +#define SF_DEVICE_ID0_AT26DF321 0x47 +#define SF_DEVICE_ID1_AT26DF321 0x00 + +#define SF_VENDOR_ID_STM 0x20 +#define SF_DEVICE_ID0_M25P32 0x20 +#define SF_DEVICE_ID1_M25P32 0x16 + +#define SF_VENDOR_ID_WINBOND 0xEF +#define SF_DEVICE_ID0_W25XXX 0x30 +#define SF_DEVICE_ID0_W25QXX 0x60 +#define SF_DEVICE_ID1_W25X80 0x14 +#define SF_DEVICE_ID1_W25X16 0x15 +#define SF_DEVICE_ID1_W25X32 0x16 +#define SF_DEVICE_ID1_W25X64 0x17 + +#define SF_VENDOR_ID_MX 0xC2 +#define SF_DEVICE_ID0_25L1605A 0x20 +#define SF_DEVICE_ID1_25L1605A 0x15 + +#define SF_VENDOR_ID_NUMONYX 0x20 +#define SF_DEVICE_ID0_M25PX16 0x71 +#define SF_DEVICE_ID1_M25PX16 0x15 + +#define SST_25LF080A_SIZE 0x00100000 +#define SST_25LF016B_SIZE 0x00200000 +#define ATMEL_AT26DF321_SIZE 0x00400000 +#define STM_M25P32_SIZE 0x00400000 +#define WINBOND_W25X80_SIZE 0x00100000 +#define WINBOND_W25X16_SIZE 0x00200000 +#define WINBOND_W25X32_SIZE 0x00400000 +#define WINBOND_W25X64_SIZE 0x00800000 +#define MX_25L1605A_SIZE 0x00200000 + +// +// Physical Sector Size on the Serial Flash device +// +#define SF_SECTOR_SIZE 0x1000 +#define SF_BLOCK_SIZE 0x8000 + +// +// Serial Flash Status Register definitions +// +#define SF_SR_BUSY 0x01 // Indicates if internal write operation is in progress +#define SF_SR_WEL 0x02 // Indicates if device is memory write enabled +#define SF_SR_BP0 0x04 // Block protection bit 0 +#define SF_SR_BP1 0x08 // Block protection bit 1 +#define SF_SR_BP2 0x10 // Block protection bit 2 +#define SF_SR_BP3 0x20 // Block protection bit 3 +#define SF_SR_WPE 0x3C // Enable write protection on all blocks +#define SF_SR_AAI 0x40 // Auto Address Increment Programming status +#define SF_SR_BPL 0x80 // Block protection lock-down + +// +// Operation Instruction definitions for the Serial Flash Device +// +#define SF_INST_WRSR 0x01 // Write Status Register +#define SF_INST_PROG 0x02 // Byte Program +#define SF_INST_READ 0x03 // Read +#define SF_INST_WRDI 0x04 // Write Disable +#define SF_INST_RDSR 0x05 // Read Status Register +#define SF_INST_WREN 0x06 // Write Enable +#define SF_INST_HS_READ 0x0B // High-speed Read +#define SF_INST_SERASE 0x20 // Sector Erase (4KB) +#define SF_INST_BERASE 0x52 // Block Erase (32KB) +#define SF_INST_64KB_ERASE 0xD8 // Block Erase (64KB) +#define SF_INST_EWSR 0x50 // Enable Write Status Register +#define SF_INST_READ_ID 0xAB // Read ID +#define SF_INST_JEDEC_READ_ID 0x9F // JEDEC Read ID +#define SF_INST_DOFR 0x3B // Dual Output Fast Read +#define SF_INST_SFDP 0x5A // Serial Flash Discovery Parameters + +#define SECTOR_SIZE_4KB 0x1000 // Common 4kBytes sector size +#define SECTOR_SIZE_64KB 0x10000 // Common 64kBytes sector size +#define BLOCK_SIZE_64KB 0x00010000 // Common 64kBytes block size +#define MAX_FWH_SIZE 0x00100000 // 8Mbit (Note that this can also be used for the 4Mbit ) + +// +// Prefix Opcode Index on the host SPI controller +// +typedef enum { + SPI_WREN, // Prefix Opcode 0: Write Enable + SPI_EWSR, // Prefix Opcode 1: Enable Write Status Register +} PREFIX_OPCODE_INDEX; + +// +// Opcode Menu Index on the host SPI controller +// +typedef enum { + SPI_READ_ID, // Opcode 0: READ ID, Read cycle with address + SPI_READ, // Opcode 1: READ, Read cycle with address + SPI_RDSR, // Opcode 2: Read Status Register, No address + SPI_WRDI_SFDP, // Opcode 3: Write Disable or Discovery Parameters, No address + SPI_SERASE, // Opcode 4: Sector Erase (4KB), Write cycle with address + SPI_BERASE, // Opcode 5: Block Erase (32KB), Write cycle with address + SPI_PROG, // Opcode 6: Byte Program, Write cycle with address + SPI_WRSR, // Opcode 7: Write Status Register, No address +} SPI_OPCODE_INDEX; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Library/StallSmmLib.h b/Vlv2TbltDevicePkg/Include/Library/StallSmmLib.h new file mode 100644 index 0000000000..364dc87679 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/StallSmmLib.h @@ -0,0 +1,45 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + SmmStallLib.h + +Abstract: + + This library provides SMM functions for Stall. + These can be used to save size and simplify code. + All contents must be runtime and SMM safe. + +--*/ + +#ifndef _SMM_STALL_LIB_H_ +#define _SMM_STALL_LIB_H_ +#include "PiDxe.h" +#include "Pi/PiSmmCis.h" +extern EFI_SMM_SYSTEM_TABLE2 *mSmst; + +/** + Delay for at least the request number of microseconds + + @param[in] Microseconds Number of microseconds to delay. + + @retval None + +**/ +VOID +SmmStall ( + IN UINTN Microseconds + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Library/UsbDeviceModeLib.h b/Vlv2TbltDevicePkg/Include/Library/UsbDeviceModeLib.h new file mode 100644 index 0000000000..4af713e4f9 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Library/UsbDeviceModeLib.h @@ -0,0 +1,186 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef __BASE_USBDEVICEMODE_LIB_H__ +#define __BASE_USBDEVICEMODE_LIB_H__ + +#pragma pack(1) +typedef struct { + UINT8 bLength; + UINT8 bDescriptorType; + UINT8 bMaxBurst; + UINT8 bmAttributes; + UINT16 wBytesPerInterval; +} endpointCompanionDescriptor; +#pragma pack() + +#pragma pack(1) +typedef struct { + UINT8 bLength; + UINT8 bDescriptorType; + UINT8 bEndpointAddress; + UINT8 bmAttributes; + UINT16 wMaxPacketSize; + UINT8 bInterval; +} endpointDescriptor; +#pragma pack() + +typedef struct { + endpointDescriptor *pEpDesc; + endpointCompanionDescriptor *pEpCompDesc; +} USB_DEV_EP_INFO; //usbdEpInfo; + +typedef struct { + VOID *pBuf; + UINT32 dataLen; +} USBD_IO_INFO; + +typedef struct { + USBD_IO_INFO ioInfo; + USB_DEV_EP_INFO epInfo; +} USBD_IO_REQ; + +UINTN +EFIAPI +usbdInitDCI ( + VOID + ); + +BOOLEAN +EFIAPI +fbInit ( + OUT VOID *pParams + ); + +BOOLEAN +EFIAPI +fbDeinit ( + VOID + ); + +BOOLEAN +EFIAPI +fbStart ( + VOID + ); + +BOOLEAN +EFIAPI +fbStop ( + VOID + ); + +BOOLEAN +EFIAPI +usbdSetMmioBar ( + UINT32 mmioBar + ); + +BOOLEAN +EFIAPI +udciDeinit ( + VOID *pUdciHndl, + UINT32 flags + ); + +BOOLEAN +EFIAPI +udciIsr ( + VOID *pUdciHndl + ); + +BOOLEAN +EFIAPI +udciConnect ( + VOID *pUdciHndl + ); + +BOOLEAN +EFIAPI +udciDisconnect ( + VOID *pUdciHndl + ); + +BOOLEAN +EFIAPI +udciSetAddress ( + VOID *pUdciHndl, + UINT8 address + ); + +BOOLEAN +EFIAPI +udciInitEp ( + VOID *pUdciHndl, + USB_DEV_EP_INFO *pEpInfo + ); + +BOOLEAN +EFIAPI +udciEnableEp ( + VOID *pUdciHndl, + USB_DEV_EP_INFO *pEpInfo + ); + +BOOLEAN +EFIAPI +udciDisableEp ( + VOID *pUdciHndl, + USB_DEV_EP_INFO *pEpInfo + ); + +BOOLEAN +EFIAPI +udciStallEp ( + VOID *pUdciHndl, + USB_DEV_EP_INFO *pEpInfo + ); + +BOOLEAN +EFIAPI +udciClearStallEp ( + VOID *pUdciHndl, + USB_DEV_EP_INFO *pEpInfo + ); + + +BOOLEAN +EFIAPI +udciEp0TxStatus ( + VOID *pUdciHndl + ); + + +BOOLEAN +EFIAPI +udciEpTxData ( + VOID *pUdciHndl, + USBD_IO_REQ *pIoReq + ); + +BOOLEAN +EFIAPI +udciEpRxData ( + VOID *pUdciHndl, + USBD_IO_REQ *pIoReq + ); + +BOOLEAN +EFIAPI +udciRegisterCallbacks ( + VOID *pUdciHndl + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Mcfg.h b/Vlv2TbltDevicePkg/Include/Mcfg.h new file mode 100644 index 0000000000..50dfc7003c --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Mcfg.h @@ -0,0 +1,74 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Mcfg.h + +Abstract: + + ACPI Memory mapped configuration space base address Description Table + implementation, based on PCI Firmware Specification Revision 3.0 final draft, + downloadable at http://www.pcisig.com/home + +**/ + +#ifndef _MCFG_H_ +#define _MCFG_H_ + +// +// Statements that include other files +// +#include +#include "McfgTable.h" +#include "Platform.h" + +// +// "MCFG" Static Resource Affinity Table +// +#define EFI_ACPI_3_0_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_SIGNATURE 0x4746434D + +// +// MCFG Definitions, see specification for details. +// +#define EFI_ACPI_OEM_MCFG_REVISION 0x00000001 + +// +// Define the number of each table type. +// This is where the table layout is modified. +// +#define EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_BASE_ADDRESS_STRUCTURE_COUNT 1 + +// +// MCFG Table definition. The table must be defined in a platform +// specific manner. +// +// +// Ensure proper structure formats +// +#pragma pack(1) + +typedef struct { + EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER Header; + +#if EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_BASE_ADDRESS_STRUCTURE_COUNT > 0 + EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_BASE_ADDRESS_STRUCTURE Segment[ + EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_BASE_ADDRESS_STRUCTURE_COUNT]; +#endif + +} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE; + +#pragma pack() + +#endif // _MCFG_H_ diff --git a/Vlv2TbltDevicePkg/Include/McfgTable.h b/Vlv2TbltDevicePkg/Include/McfgTable.h new file mode 100644 index 0000000000..39461a2cc4 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/McfgTable.h @@ -0,0 +1,70 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + McfgTable.h + +Abstract: + + ACPI Memory mapped configuration space base address Description Table + definition, based on PCI Firmware Specification Revision 3.0 final draft, + downloadable at http://www.pcisig.com/home + +**/ + +#ifndef _MCFG_TABLE_H_ +#define _MCFG_TABLE_H_ + +// +// Include files +// +#include + +// +// Ensure proper structure formats +// +#pragma pack(1) + +// +// MCFG Revision (defined in spec) +// +#define EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_REVISION 0x01 + +// +// MCFG Structure Definitions +// +// +// Memory Mapped Enhanced Configuration Base Address Allocation +// Structure Definition +// +typedef struct { + UINT64 BaseAddress; + UINT16 PciSegmentGroupNumber; + UINT8 StartBusNumber; + UINT8 EndBusNumber; + UINT32 Reserved; +} EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_BASE_ADDRESS_STRUCTURE; + +// +// MCFG Table header definition. The rest of the table +// must be defined in a platform specific manner. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 Reserved; +} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER; + +#pragma pack() + +#endif // _MCFG_TABLE_H diff --git a/Vlv2TbltDevicePkg/Include/Platform.h b/Vlv2TbltDevicePkg/Include/Platform.h new file mode 100644 index 0000000000..fa651f595b --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Platform.h @@ -0,0 +1,138 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Platform.h + +Abstract: + + Pinetrail platform specific information. + +**/ + +#ifndef _PLATFORM_H +#define _PLATFORM_H + +#include "ChipsetAccess.h" +#include "PlatformBaseAddresses.h" + + +// +// Number of P & T states supported. +// +#define NPTM_P_STATES_SUPPORTED 16 +#define NPTM_T_STATES_SUPPORTED 8 + +// +// I/O APIC IDs, the code uses math to generate the numbers +// instead of using these defines. +// +#define ICH_IOAPIC (1 << 0) +#define ICH_IOAPIC_ID 0x08 + +// +// Possible SMBus addresses that will be present. +// +#define SMBUS_ADDR_CH_A_1 0xA0 +#define SMBUS_ADDR_CH_A_2 0xA2 +#define SMBUS_ADDR_CH_B_1 0xA4 +#define SMBUS_ADDR_CH_B_2 0xA6 +#define SMBUS_ADDR_CH_C_1 0xA8 +#define SMBUS_ADDR_CH_C_2 0xAA +#define SMBUS_ADDR_CH_D_1 0xAC +#define SMBUS_ADDR_CH_D_2 0xAE +#define SMBUS_ADDR_HOST_CLK_BUFFER 0xDC +#define SMBUS_ADDR_ICH_SLAVE 0x44 +#define SMBUS_ADDR_HECETA 0x5C +#define SMBUS_ADDR_SMBARP 0xC2 +#define SMBUS_ADDR_82573E 0xC6 +#define SMBUS_ADDR_CLKCHIP 0xD2 +#define SMBUS_ADDR_BRD_REV 0x4E +#define SMBUS_ADDR_DB803 0x82 + +// +// SMBus addresses that used on this platform. +// +#define PLATFORM_SMBUS_RSVD_ADDRESSES { \ + SMBUS_ADDR_CH_A_1, \ + SMBUS_ADDR_CH_A_2, \ + SMBUS_ADDR_HOST_CLK_BUFFER, \ + SMBUS_ADDR_ICH_SLAVE, \ + SMBUS_ADDR_SMBARP, \ + SMBUS_ADDR_CLKCHIP, \ + SMBUS_ADDR_BRD_REV, \ + SMBUS_ADDR_DB803 \ + } + +// +// Count of addresses present in PLATFORM_SMBUS_RSVD_ADDRESSES. +// +#define PLATFORM_NUM_SMBUS_RSVD_ADDRESSES 8 + +// +// CMOS usage +// +#define CMOS_CPU_BSP_SELECT 0x10 +#define CMOS_CPU_UP_MODE 0x11 +#define CMOS_CPU_RATIO_OFFSET 0x12 +#define CMOS_CPU_CORE_HT_OFFSET 0x13 +#define CMOS_EFI_DEBUG 0x14 +#define CMOS_CPU_BIST_OFFSET 0x15 +#define CMOS_CPU_VMX_OFFSET 0x16 +#define CMOS_ICH_PORT80_OFFSET 0x17 +#define CMOS_PLATFORM_DESIGNATOR 0x18 // Second bank CMOS location of Platform ID. +#define CMOS_VALIDATION_TEST_BYTE 0x19 // BIT0 - Validation mailbox for UPonDP. +#define CMOS_SERIAL_BAUD_RATE 0x1A // 0=115200; 1=57600; 2=38400; 3=19200; 4=9600 +#define CMOS_DCU_MODE_OFFSET 0x1B +#define CMOS_VR11_SET_OFFSET 0x1C +#define CMOS_SBSP_TO_AP_COMM 0x20 // SEC code use ONLY!!! +#define CMOS_RESET_TYPE_BY_OS 0x52 +#define TCG_CMOS_MOR_AREA_OFFSET 0x65 // Also Change in Universal\Security\Tpm\PhysicalPresence\Dxe\PhysicalPresence.c & +#define CMOS_S4_WAKEUP_FLAG_ADDRESS 0x6E +#define ACPI_TPM_REQUEST 0x75 +#define ACPI_TPM_LAST_REQUEST 0x76 +#define CMOS_BOOT_FLAG_ADDRESS 0x7E + +// +// GPIO Index Data Structure. +// +typedef struct { + UINT8 Register; + UINT32 Value; +} ICH_GPIO_DEV; + +// +// CPU Equates +// +#define MAX_THREAD 2 +#define MAX_CORE 1 +#define MAX_DIE 2 +#define MAX_CPU_SOCKET 1 +#define MAX_CPU_NUM (MAX_THREAD * MAX_CORE * MAX_DIE * MAX_CPU_SOCKET) + +#define MEM64_LEN 0x00100000000 +#define RES_MEM64_36_BASE 0x01000000000 - MEM64_LEN // 2^36 +#define RES_MEM64_36_LIMIT 0x01000000000 - 1 // 2^36 +#define RES_MEM64_39_BASE 0x08000000000 - MEM64_LEN // 2^39 +#define RES_MEM64_39_LIMIT 0x08000000000 - 1 // 2^39 +#define RES_MEM64_40_BASE 0x10000000000 - MEM64_LEN // 2^40 +#define RES_MEM64_40_LIMIT 0x10000000000 - 1 // 2^40 + +#define PLATFORM_MAX_BUS_NUM 0x3f +#define V_DEFAULT_SUBSYSTEM_DEVICE_ID 0x574d +#define V_DEFAULT_SUBSYSTEM_DEVICE_ID_KT 0x544b +#define V_DEFAULT_SUBSYSTEM_VENDOR_ID 0x8086 + +#endif diff --git a/Vlv2TbltDevicePkg/Include/PlatformBootMode.h b/Vlv2TbltDevicePkg/Include/PlatformBootMode.h new file mode 100644 index 0000000000..5335ab95be --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/PlatformBootMode.h @@ -0,0 +1,40 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PlatformBootMode.h + +Abstract: + + EFI Platform Boot Mode + +Revision History + +--*/ + +#ifndef _EFI_PLATFORM_BOOT_MODE_H_ +#define _EFI_PLATFORM_BOOT_MODE_H_ + +// +// Global ID for the Platform Boot Mode Protocol. +// +#define MANUFACTURE_SETUP_NAME L"MfgDefault" +#define SAFE_SETUP_NAME L"SetupDefault" +#define OEM_DEFAULTS_SETUP_NAME L"OemDefault" +#define CUSTOM_DEFAULTS_SETUP_NAME L"CustomDefault" + +#endif + + diff --git a/Vlv2TbltDevicePkg/Include/PlatformDefinitions.h b/Vlv2TbltDevicePkg/Include/PlatformDefinitions.h new file mode 100644 index 0000000000..edff69d194 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/PlatformDefinitions.h @@ -0,0 +1,48 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PlatformDefinitions.h + +Abstract: + + This header file provides platform specific definitions used by other modules + for platform specific initialization. + + THIS FILE SHOULD ONLY CONTAIN #defines BECAUSE IT IS CONSUMED BY NON-C MODULES + (ASL and VFR) + + This file should not contain addition or other operations that an ASL compiler or + VFR compiler does not understand. + +--*/ + +#ifndef _PLATFORM_DEFINITIONS_H_ +#define _PLATFORM_DEFINITIONS_H_ + + +// +// Platform Base Address definitions +// +#define PCIEX_BASE_ADDRESS EDKII_GLUE_PciExpressBaseAddress // Pci Express Configuration Space Base Address + +#define PCIEX_LENGTH PLATFORM_PCIEXPRESS_LENGTH + +#define THERMAL_BASE_ADDRESS 0xFED08000 + +#ifndef MCH_BASE_ADDRESS +#define MCH_BASE_ADDRESS 0xFED10000 // MCH Register Base Address +#endif +#endif diff --git a/Vlv2TbltDevicePkg/Include/Ppi/MfgMemoryTest.h b/Vlv2TbltDevicePkg/Include/Ppi/MfgMemoryTest.h new file mode 100644 index 0000000000..fc4744822f --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Ppi/MfgMemoryTest.h @@ -0,0 +1,47 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + BaseMemoryTest.h + +Abstract: + + Pei memory test PPI as defined in Tiano + + Used to Pei memory test in PEI + +--*/ + +#ifndef _BASE_MEMORY_TEST_H_ +#define _BASE_MEMORY_TEST_H_ + +typedef struct _PEI_MFG_MEMORY_TEST_PPI PEI_MFG_MEMORY_TEST_PPI; + +typedef +EFI_STATUS +(EFIAPI *PEI_MFG_MEMORY_TEST) ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN PEI_MFG_MEMORY_TEST_PPI * This, + IN UINT32 BeginAddress, + IN UINT32 MemoryLength + ); + +typedef struct _PEI_MFG_MEMORY_TEST_PPI { + PEI_MFG_MEMORY_TEST MfgMemoryTest; +}PEI_MFG_MEMORY_TEST_PPI; + + +extern EFI_GUID gPeiMfgMemoryTestPpiGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Ppi/Sha256Hash.h b/Vlv2TbltDevicePkg/Include/Ppi/Sha256Hash.h new file mode 100644 index 0000000000..8511b4c935 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Ppi/Sha256Hash.h @@ -0,0 +1,136 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + Speaker.h + +Abstract: + + EFI Speaker Interface Protocol + + + +--*/ + +#ifndef _PEI_SHA256_HASH_H +#define _PEI_SHA256_HASH_H + +// +// Global ID Speaker Interface +// +#define PEI_SHA256_HASH_PPI_GUID \ + { \ + 0x950e191b, 0x8524, 0x4f51, 0x80, 0xa1, 0x5c, 0x4f, 0x1b, 0x3, 0xf3, 0x5c \ + } + +typedef struct _PEI_SHA256_HASH_PPI PEI_SHA256_HASH_PPI; + +/** + @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 + ); + +// +// Ppi definition +// +typedef struct _PEI_SHA256_HASH_PPI { + // + // 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; + +} PEI_SHA256_HASH_PPI; + +extern EFI_GUID gPeiSha256HashPpiGuid; +#endif diff --git a/Vlv2TbltDevicePkg/Include/Ppi/Speaker.h b/Vlv2TbltDevicePkg/Include/Ppi/Speaker.h new file mode 100644 index 0000000000..2dfdafbd6f --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Ppi/Speaker.h @@ -0,0 +1,70 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + Speaker.h + +Abstract: + + EFI Speaker Interface Protocol + + + +--*/ + +#ifndef _PEI_SPEAKER_IF_H +#define _PEI_SPEAKER_IF_H + +// +// Global ID Speaker Interface +// +#define PEI_SPEAKER_INTERFACE_PPI_GUID \ + { \ + 0x30ac275e, 0xbb30, 0x4b84, 0xa1, 0xcd, 0x0a, 0xf1, 0x32, 0x2c, 0x89, 0xc0 \ + } + +typedef struct _PEI_SPEAKER_IF_PPI PEI_SPEAKER_IF_PPI; + +// +// Beep Code +// +typedef +EFI_STATUS +(EFIAPI *EFI_SPEAKER_GENERATE_BEEP) ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN NumberOfBeep, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ); + +// +// Set Frequency +// +typedef +EFI_STATUS +(EFIAPI *EFI_SPEAKER_SET_FREQUENCY) ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Frequency + ); + +// +// Protocol definition +// +typedef struct _PEI_SPEAKER_IF_PPI { + EFI_SPEAKER_SET_FREQUENCY SetSpeakerToneFrequency; + EFI_SPEAKER_GENERATE_BEEP GenerateBeep; +} PEI_SPEAKER_IF_PPI; + +extern EFI_GUID gPeiSpeakerInterfacePpiGuid; +#endif diff --git a/Vlv2TbltDevicePkg/Include/Ppi/UsbController.h b/Vlv2TbltDevicePkg/Include/Ppi/UsbController.h new file mode 100644 index 0000000000..dc6468a045 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Ppi/UsbController.h @@ -0,0 +1,90 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + Define APIs to retrieve USB Host Controller Info such as controller type and + I/O Port Base Address. + + +**/ + +#ifndef _PEI_USB_CONTROLLER_PPI_H_ +#define _PEI_USB_CONTROLLER_PPI_H_ + +// +// Global ID for the PEI_USB_CONTROLLER_PPI. +// +#define PEI_USB_CONTROLLER_PPI_GUID \ + { \ + 0x3bc1f6de, 0x693e, 0x4547,{ 0xa3, 0x0, 0x21, 0x82, 0x3c, 0xa4, 0x20, 0xb2} \ + } + +// +// Forward declaration for the PEI_USB_CONTROLLER_PPI. +// +typedef struct _PEI_USB_CONTROLLER_PPI PEI_USB_CONTROLLER_PPI; + +// +// This bit is used in the ControllerType return parameter of GetUsbController() +// to identify the USB Host Controller type as UHCI +// +#define PEI_UHCI_CONTROLLER 0x01 + +// +// This bit is used in the ControllerType return parameter of GetUsbController() +// to identify the USB Host Controller type as OHCI +// +#define PEI_OHCI_CONTROLLER 0x02 + +// +// This bit is used in the ControllerType return parameter of GetUsbController() +// to identify the USB Host Controller type as EHCI +// +#define PEI_EHCI_CONTROLLER 0x03 + +/** + Retrieve USB Host Controller Info such as controller type and I/O Base Address. + + @param[in] PeiServices The pointer to the PEI Services Table. + @param[in] This The pointer to this instance of the PEI_USB_CONTROLLER_PPI. + @param[in] ControllerId The ID of the USB controller. + @param[out] ControllerType On output, returns the type of the USB controller. + @param[out] BaseAddress On output, returns the base address of UHCI's I/O ports + if UHCI is enabled or the base address of EHCI's MMIO + if EHCI is enabled. + + @retval EFI_SUCCESS USB controller attributes were returned successfully. + @retval EFI_INVALID_PARAMETER ControllerId is greater than the maximum number + of USB controller supported by this platform. + +**/ +typedef +EFI_STATUS +(EFIAPI *PEI_GET_USB_CONTROLLER)( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_CONTROLLER_PPI *This, + IN UINT8 UsbControllerId, + OUT UINTN *ControllerType, + OUT UINTN *BaseAddress + ); + +// +// This PPI contains a single service to retrieve the USB Host Controller type +// and the base address of the I/O ports used to access the USB Host Controller. +// +struct _PEI_USB_CONTROLLER_PPI { + PEI_GET_USB_CONTROLLER GetUsbController; +}; + +extern EFI_GUID gPeiUsbControllerPpiGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/CK505ClockPlatformInfo.h b/Vlv2TbltDevicePkg/Include/Protocol/CK505ClockPlatformInfo.h new file mode 100644 index 0000000000..87c1c37686 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/CK505ClockPlatformInfo.h @@ -0,0 +1,131 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + CK505ClockPlatformInfo.h + +Abstract: + + Protocol to communicate product clock routing information. + +GUID Info: + {3C485EA4-449A-46ce-BB08-2A336EA96B4E} + 0x3c485ea4, 0x449a, 0x46ce, 0xbb, 0x8, 0x2a, 0x33, 0x6e, 0xa9, 0x6b, 0x4e); + +**/ + +#ifndef _CLOCK_PLATFORM_INFO_H_ +#define _CLOCK_PLATFORM_INFO_H_ + + +#define EFI_CK505_CLOCK_PLATFORM_INFO_GUID \ + {0x3c485ea4, 0x449a, 0x46ce, 0xbb, 0x8, 0x2a, 0x33, 0x6e, 0xa9, 0x6b, 0x4e} + +// +// Structure to hold register modifications +// +typedef enum { + None = 0x00000000, + nICS9LP505_1 = 0x00000001, + nICS9LP505_2 = 0x00000002, + nIDTCV163 = 0x00000004, + nIDTCV174 = 0x00000008, + nSLG505YC56 = 0x00000010, + nSLG505YC64 = 0x00000020, + nCY28505 = 0x00000040, + nCY28505_2 = 0x00000080, + nCY28505LF = 0x00000100, + nPI6C505_OLD = 0x00000200, + nPI6C505_RevD = 0x00000400, + nGENERIC_505 = 0x00000800, + nSLG505YC264 = 0x00001000, + nIDTCV183 = 0x00002000, + nSLG505YC256 = 0x00004000, + nIDTCV184 = 0x00008000, + nIDTCV190 = 0x00010000, + All = 0xFFFFFFFF +} EFI_CLOCKS_SUPPORTED; + +typedef enum { + Disabled, + Enabled, + EnabledWithoutSwitch, + EnabledWithSwitch +} EFI_SIGNAL_STATE; + +typedef enum { + SrcClk11, + SrcClk10, + SrcClk9, + SrcClk8, + SrcClk7, + SrcClk6, + SrcClk5, + SrcClk4, + SrcClk3, + SrcClk2, + SrcClk1, + SrcClk0, + CpuClk1, + CpuClk0, + Ref0, + Dot96, + Usb48, + PciClkF5, + PciClk4, + PciClk3, + PciClk2, + PciClk1, + PciClk0, + SaveClockConfiguration, + MePresent, + Cr_A, + Cr_B, + Cr_C, + Cr_D, + Cr_E, + Cr_F, + Cr_G, + Cr_H, + Clk_None // Dummy entry for dynamic detection +} EFI_CLOCK_SIGNAL_NAME; + +typedef struct { + EFI_CLOCK_SIGNAL_NAME Signal; + EFI_SIGNAL_STATE State; + EFI_CLOCKS_SUPPORTED Supported; +} EFI_STATIC_SIGNALS; + +typedef struct { + BOOLEAN BehindBridge; + UINT16 BridgeBus; + UINT16 BridgeDev; + UINT16 BridgeFunction; + UINT16 TargetDevice; + EFI_CLOCK_SIGNAL_NAME Signal; +} EFI_DYNAMIC_SIGNALS; + + +typedef struct { + EFI_STATIC_SIGNALS *StaticClockTable; + UINTN StaticClockTableCount; + EFI_STATIC_SIGNALS *SxClockTable; + UINTN SxClockTableCount; + EFI_STATIC_SIGNALS *DynamicDisabledClocksTable; + UINTN DynamicDisabledClocksTableCount; +} EFI_CLOCK_PLATFORM_INFO; + +extern EFI_GUID gEfiCk505ClockPlatformInfoGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/EnhancedSpeedstep.h b/Vlv2TbltDevicePkg/Include/Protocol/EnhancedSpeedstep.h new file mode 100644 index 0000000000..e71778f833 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/EnhancedSpeedstep.h @@ -0,0 +1,81 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +Module Name: + + EnhancedSpeedstep.h + +Abstract: + + Enhanced Speedstep protocol + + The Enhanced Speedstep Protocol support. + +**/ + +#ifndef _ENHANCED_SPEEDSTEP_H_ +#define _ENHANCED_SPEEDSTEP_H_ + +#define ENHANCED_SPEEDSTEP_PROTOCOL_GUID \ + { \ + 0x91a1ddcf, 0x5374, 0x4939, 0x89, 0x51, 0xd7, 0x29, 0x3f, 0x1a, 0x78, 0x6f \ + } + +typedef struct _ENHANCED_SPEEDSTEP_PROTOCOL ENHANCED_SPEEDSTEP_PROTOCOL; + +typedef struct { + UINT8 Version; // EIST State format + UINT8 Size; // Size of element + UINT32 RatioStep; // Step + UINT32 MinRatio; // Calculated min ratio + UINT32 MaxRatio; // Calculated max ratio + UINT32 MinCoreFreq; // Calculated min freq + UINT32 MaxCoreFreq; // Calculated max freq + UINT32 MinPower; // Calculated min power + UINT32 MaxPower; // Calculated max power + UINT32 NumStates; // Number of states +} EIST_INFORMATION; + +typedef struct { + UINT32 CoreFrequency; + UINT32 Power; + UINT32 TransitionLatency; + UINT32 BusMasterLatency; + UINT32 Control; + UINT32 Status; +} EFI_ACPI_CPU_PSS_STATE; + +typedef +EFI_STATUS +(EFIAPI *GET_EIST_TABLE) ( + IN ENHANCED_SPEEDSTEP_PROTOCOL *This, + OUT EIST_INFORMATION **EistInformation, + OUT VOID **PssStates + ); + +struct _ENHANCED_SPEEDSTEP_PROTOCOL { + UINT32 ProcApicId; + GET_EIST_TABLE GetEistTable; +}; + +// +// There will be an instance of this protocol for every processor +// in the system. ProcNumber is used to manage all the different +// processors in the system and passed into the MP protocol +// to run code streams on application processors +// +extern EFI_GUID gEnhancedSpeedstepProtocolGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/GlobalNvsArea.h b/Vlv2TbltDevicePkg/Include/Protocol/GlobalNvsArea.h new file mode 100644 index 0000000000..231c8c018d --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/GlobalNvsArea.h @@ -0,0 +1,484 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + + This program and the accompanying materials are licensed and made available under + + the terms and conditions of the BSD License that accompanies this distribution. + + The full text of the license may be found at + + http://opensource.org/licenses/bsd-license.php. + + + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + + +Module Name: + + GlobalNvsArea.h + +Abstract: + + 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. + +**/ + + +#ifndef _GLOBAL_NVS_AREA_H_ +#define _GLOBAL_NVS_AREA_H_ + +// +// Includes +// +#define GLOBAL_NVS_DEVICE_ENABLE 1 +#define GLOBAL_NVS_DEVICE_DISABLE 0 + +// +// Forward reference for pure ANSI compatibility +// + +//EFI_FORWARD_DECLARATION (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 } + +// +// Revision id - Added TPM related fields +// +#define GLOBAL_NVS_AREA_RIVISION_1 1 + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gEfiGlobalNvsAreaProtocolGuid; + +// +// Global NVS Area definition +// +#pragma pack (1) +typedef struct { + // + // Miscellaneous Dynamic Values, the definitions below need to be matched + // GNVS definitions in Platform.ASL + // + UINT16 OperatingSystem; // 00 + UINT8 SmiFunction; // 02 SMI function call via IO Trap + UINT8 SmiParameter0; // 03 + UINT8 SmiParameter1; // 04 + UINT8 SciFunction; // 05 SCI function call via _L00 + UINT8 SciParameter0; // 06 + UINT8 SciParameter1; // 07 + UINT8 GlobalLock; // 08 Global lock function call + UINT8 LockParameter0; // 09 + UINT8 LockParameter1; // 10 + UINT32 Port80DebugValue; // 11 + UINT8 LidState; // 15 Open = 1 + UINT8 PowerState; // 16 AC = 1 + UINT8 DebugState; // 17 + + + // + // Thermal Policy Values + // + UINT8 EnableThermalOffset; // 18 ThermalOffset for KSC + UINT8 Reserved1; // 19 + UINT8 Reserved2; // 20 + UINT8 PassiveThermalTripPoint; // 21 + UINT8 PassiveTc1Value; // 22 + UINT8 PassiveTc2Value; // 23 + UINT8 PassiveTspValue; // 24 + UINT8 CriticalThermalTripPoint; // 25 + UINT8 ReserveD; + UINT8 BspDigitalThermalSensorTemperature; // 27 Temperature of BSP + UINT8 ApDigitalThermalSensorTemperature; // 28 Temperature of AP + UINT8 DigitalThermalSensorSmiFunction; // 29 SMI function call via DTS IO Trap + + // + // Battery Support Values + // + UINT8 NumberOfBatteries; // 30 + UINT8 BatteryCapacity0; // 31 Battery 0 Stored Capacity + UINT8 BatteryCapacity1; // 32 Battery 1 Stored Capacity + UINT8 BatteryCapacity2; // 33 Battery 2 Stored Capacity + UINT8 BatteryStatus0; // 34 Battery 0 Stored Status + UINT8 BatteryStatus1; // 35 Battery 1 Stored Status + UINT8 BatteryStatus2; // 36 Battery 2 Stored Status + + // NOTE: Do NOT Change the Offset of Revision Field + UINT8 Revision; // 37 Revision of the structure EFI_GLOBAL_NVS_AREA + UINT8 Reserved3[2]; // 38:39 + + // + // Processor Configuration Values + // + UINT8 ApicEnable; // 40 APIC Enabled by SBIOS (APIC Enabled = 1) + UINT8 LogicalProcessorCount; // 41 Processor Count Enabled (MP Enabled != 0) + UINT8 CurentPdcState0; // 42 PDC settings, Processor 0 + UINT8 CurentPdcState1; // 43 PDC settings, Processor 1 + UINT8 MaximumPpcState; // 44 Maximum PPC state + UINT32 PpmFlags; // 45:48 PPM configuration flags, same as CFGD + UINT8 Reserved4[1]; // 49 + + // + // SIO Configuration Values + // + UINT8 DockedSioPresent; // 50 Dock SIO Present + UINT8 DockComA; // 51 COM A Port + UINT8 DockComB; // 52 COM B Port + UINT8 LptP; // 53 LPT Port + UINT8 DockFdc; // 54 FDC Port + UINT8 OnboardCom; // 55 Onboard COM Port + UINT8 OnboardComCir; // 56 Onboard COM CIR Port + + UINT8 WPCN381U; // 57 + UINT8 NPCE791x; // 58 + UINT8 Reserved5[1]; // 59 + + // + // Internal Graphics Device Values + // + UINT8 IgdState; // 60 IGD State (Primary Display = 1) + UINT8 DisplayToggleList; // 61 Display Toggle List Selection + UINT8 CurrentDeviceList; // 62 Current Attached Device List + UINT8 PreviousDeviceList; // 63 Previous Attached Device List + UINT16 CurrentDisplayState; // 64 Current Display State + UINT16 NextDisplayState; // 66 Next Display State + UINT16 SetDisplayState; // 68 Set Display State + UINT8 NumberOfValidDeviceId; // 70 Number of Valid Device IDs + UINT32 DeviceId1; // 71 Device ID 1 + UINT32 DeviceId2; // 75 Device ID 2 + UINT32 DeviceId3; // 79 Device ID 3 + UINT32 DeviceId4; // 83 Device ID 4 + UINT32 DeviceId5; // 87 Device ID 5 + + UINT32 AKsv0; // 91:94 First four bytes of AKSV (manufacturing mode) + UINT8 AKsv1; // 95 Fifth byte of AKSV (manufacturing mode + + UINT8 Reserved6[7]; // 96:102 + + // + // Backlight Control Values + // + UINT8 BacklightControlSupport; // 103 Backlight Control Support + UINT8 BrightnessPercentage; // 104 Brightness Level Percentage + + // + // Ambient Light Sensor Values + // + UINT8 AlsEnable; // 105 Ambient Light Sensor Enable + UINT8 AlsAdjustmentFactor; // 106 Ambient Light Adjusment Factor + UINT8 LuxLowValue; // 107 LUX Low Value + UINT8 LuxHighValue; // 108 LUX High Value + + UINT8 Reserved7[1]; // 109 + + // + // Extended Mobile Access Values + // + UINT8 EmaEnable; // 110 EMA Enable + UINT16 EmaPointer; // 111 EMA Pointer + UINT16 EmaLength; // 113 EMA Length + + UINT8 Reserved8[1]; // 115 + + // + // Mobile East Fork Values + // + UINT8 MefEnable; // 116 Mobile East Fork Enable + + // + // PCIe Dock Status + // + UINT8 PcieDockStatus; // 117 PCIe Dock Status + + UINT8 Reserved9[2]; // 118:119 + + // + // TPM Registers + // + UINT8 TpmPresent; // 120 TPM Present + UINT8 TpmEnable; // 121 TPM Enable + + UINT8 MorData; // 122 Memory Overwrite Request Data + UINT8 TcgParamter; // 123 Used for save the Mor and/or physical presence paramter + UINT32 PPResponse; // 124 Physical Presence request operation response + UINT8 PPRequest; // 128 Physical Presence request operation + UINT8 LastPPRequest; // 129 Last Physical Presence request operation + + // + // SATA Values + // + UINT8 GtfTaskFileBufferPort0[7]; // 130 GTF Task File Buffer for Port 0 + UINT8 GtfTaskFileBufferPort2[7]; // 137 GTF Task File Buffer for Port 2 + UINT8 IdeMode; // 144 IDE Mode (Compatible\Enhanced) + UINT8 GtfTaskFileBufferPort1[7]; // 145:151 GTF Task File Buffer for Port 1 + + UINT8 Reserved111[10]; // 152:161 + UINT64 BootTimeLogAddress; // 162:169 Boot Time Log Table Address + + UINT32 IgdOpRegionAddress; // 170 IGD OpRegion Starting Address + UINT8 IgdBootType; // 174 IGD Boot Type CMOS option + UINT8 IgdPanelType; // 175 IGD Panel Type CMOs option + UINT8 IgdTvFormat; // 176 IGD TV Format CMOS option + UINT8 IgdTvMinor; // 177 IGD TV Minor Format CMOS option + UINT8 IgdPanelScaling; // 178 IGD Panel Scaling + UINT8 IgdBlcConfig; // 179 IGD BLC Configuration + UINT8 IgdBiaConfig; // 180 IGD BIA Configuration + UINT8 IgdSscConfig; // 181 IGD SSC Configuration + UINT8 Igd409; // 182 IGD 0409 Modified Settings Flag + UINT8 Igd509; // 183 IGD 0509 Modified Settings Flag + UINT8 Igd609; // 184 IGD 0609 Modified Settings Flag + UINT8 Igd709; // 185 IGD 0709 Modified Settings Flag + UINT8 IgdPowerConservation; // 186 IGD Power Conservation Feature Flag + UINT8 IgdDvmtMemSize; // 187 IGD DVMT Memory Size + UINT8 IgdFunc1Enable; // 188 IGD Function 1 Enable + UINT8 IgdHpllVco; // 189 HPLL VCO + UINT32 NextStateDid1; // 190 Next state DID1 for _DGS + UINT32 NextStateDid2; // 194 Next state DID2 for _DGS + UINT32 NextStateDid3; // 198 Next state DID3 for _DGS + UINT32 NextStateDid4; // 202 Next state DID4 for _DGS + UINT32 NextStateDid5; // 206 Next state DID5 for _DGS + UINT32 NextStateDid6; // 210 Next state DID6 for _DGS + UINT32 NextStateDid7; // 214 Next state DID7 for _DGS + UINT32 NextStateDid8; // 218 Next state DID8 for _DGS + UINT8 IgdSciSmiMode; // 222 GMCH SMI/SCI mode (0=SCI) + UINT8 IgdPAVP; // 223 IGD PAVP data + UINT8 IgdSelfRefresh; // 224 IGD Self Refresh + UINT8 PcieOSCControl; // 225 PCIE OSC Control + UINT8 NativePCIESupport; // 226 Native PCI Express Support + + // + // USB Sideband Deferring Support + // + UINT8 HostAlertVector; // 227 GPE vector used for HOST_ALERT + UINT8 HostAlertPio; // 228 PIO of USB device used for HOST_ALERT + + UINT8 Reserved112[27]; // 229 + UINT32 NvIgOpRegionAddress; // 256 NVIG support + UINT32 NvHmOpRegionAddress; // 260 NVHM support + UINT32 ApXmOpRegionAddress; // 264 AMDA support + UINT32 DeviceId6; // 268 Device ID 6 + UINT32 DeviceId7; // 272 Device ID 7 + UINT32 DeviceId8; // 276 Device ID 8 + UINT32 EndpointBaseAddress; // 280 PEG Endpoint PCIe Base Address + UINT32 CapStrPresence; // 284 PEG Endpoint Capability Structure Presence + UINT32 EndpointPcieCapBaseAddress; // 288 PEG Endpoint PCIe Capability Structure Base Address + UINT32 EndpointVcCapBaseAddress; // 292 PEG Endpoint Virtual Channel Capability Structure Base Address + UINT32 XPcieCfgBaseAddress; // 296 Any Device's PCIe Config Space Base Address + UINT32 OccupiedBuses1; // 300 Occupied Buses from 0 to 31 + UINT32 OccupiedBuses2; // 304 Occupied Buses from 32 to 63 + UINT32 OccupiedBuses3; // 308 Occupied Buses from 64 to 95 + UINT32 OccupiedBuses4; // 312 Occupied Buses from 96 to 127 + UINT32 OccupiedBuses5; // 316 Occupied Buses from 128 to 159 + UINT32 OccupiedBuses6; // 320 Occupied Buses from 160 to 191 + UINT32 OccupiedBuses7; // 324 Occupied Buses from 192 to 223 + UINT32 OccupiedBuses8; // 328 Occupied Buses from 224 to 255 + UINT8 UartSelection; // 332 UART Interface Selection 0: Internal; 1: SIO + UINT8 PcuUart1Enable; // 333 PCU UART 1 Enabled + UINT8 PcuUart2Enable; // 334 PCU UART 2 Enabled + + UINT32 LPEBar0; // 335~338 LPE Bar0 + UINT32 LPEBar1; // 339~342 LPE Bar1 + + UINT32 LPEBar2; // 343~346 LPE Bar2 + UINT8 AcSetup; // 347 For Ac Powered Config option - IST applet + UINT8 BatterySetup; // 348 For Battery Powered Config option - IST applet + UINT8 PlatformFlavor; // 349 0:unknown 1: Mobile; 2: desktop + UINT8 Reserved113[1]; // 350 + + UINT8 IsctReserve; // 351 ISCT / AOAC Configuration + UINT8 XhciMode; // 352 xHCI mode + UINT8 PmicEnable; // 353 PMIC enable + + UINT8 LpeEnable; // 354 LPE enable + UINT32 ISPAddr; // 355 ISP Base address + UINT8 ISPDevSel; // 359 ISP device enabled selection 0: Disabled; 1: PCI Device 2; 2: PCI Device 3 + + // + // Lpss controllers + // + UINT32 PCIBottomAddress; //360 ((4+8+6)*4+2)*4=296 + UINT32 PCITopAddress; //364 + + UINT32 LDMA1Addr; // 368 + UINT32 LDMA1Len; // 372 + UINT32 LDMA11Addr; // 376 + UINT32 LDMA11Len; // 380 + UINT32 PWM1Addr; // 384 PWM1 + UINT32 PWM1Len; // 388 + UINT32 PWM11Addr; // 392 + UINT32 PWM11Len; // 396 + UINT32 PWM2Addr; // 400 PWM2 + UINT32 PWM2Len; // 404 + UINT32 PWM21Addr; // 408 + UINT32 PWM21Len; // 412 + UINT32 UART1Addr; // 416 UART1 + UINT32 UART1Len; // 420 + UINT32 UART11Addr; // 424 UART1 + UINT32 UART11Len; // 428 + UINT32 UART2Addr; // 432 UART2 + UINT32 UART2Len; // 436 + UINT32 UART21Addr; // 440 UART2 + UINT32 UART21Len; // 444 + UINT32 SPIAddr; // 448 SPI + UINT32 SPILen; // 452 + UINT32 SPI1Addr; // 456 + UINT32 SPI1Len; // 460 + + UINT32 LDMA2Addr; // 464 + UINT32 LDMA2Len; // 468 + UINT32 LDMA21Addr; // 472 + UINT32 LDMA21Len; // 476 + UINT32 I2C1Addr; // 480 I2C1 + UINT32 I2C1Len; // 484 + UINT32 I2C11Addr; // 488 I2C1 + UINT32 I2C11Len; // 492 + UINT32 I2C2Addr; // 496 I2C2 + UINT32 I2C2Len; // 500 + UINT32 I2C21Addr; // 504 I2C2 + UINT32 I2C21Len; // 508 + UINT32 I2C3Addr; // 512 I2C3 + UINT32 I2C3Len; // 516 + UINT32 I2C31Addr; // 520 I2C3 + UINT32 I2C31Len; // 524 + UINT32 I2C4Addr; // 528 I2C4 + UINT32 I2C4Len; // 532 + UINT32 I2C41Addr; // 536 I2C4 + UINT32 I2C41Len; // 540 + UINT32 I2C5Addr; // 544 I2C5 + UINT32 I2C5Len; // 548 + UINT32 I2C51Addr; // 552 I2C5 + UINT32 I2C51Len; // 556 + UINT32 I2C6Addr; // 560 I2C6 + UINT32 I2C6Len; // 564 + UINT32 I2C61Addr; // 566 I2C6 + UINT32 I2C61Len; // 570 + UINT32 I2C7Addr; // 574 I2C7 + UINT32 I2C7Len; // 578 + UINT32 I2C71Addr; // 582 I2C7 + UINT32 I2C71Len; // 586 + + // + // Scc controllers + // + UINT32 eMMCAddr; // 590 EMMC + UINT32 eMMCLen; // 594 + UINT32 eMMC1Addr; // 598 + UINT32 eMMC1Len; // 602 + UINT32 SDIOAddr; // 606 SDIO + UINT32 SDIOLen; // 610 + UINT32 SDIO1Addr; // 614 + UINT32 SDIO1Len; // 618 + UINT32 SDCardAddr; // 622 SDCard + UINT32 SDCardLen; // 626 + UINT32 SDCard1Addr; // 630 + UINT32 SDCard1Len; // 636 + UINT32 MipiHsiAddr; // 640 MIPI-HSI + UINT32 MipiHsiLen; // 644 + UINT32 MipiHsi1Addr; // 648 + UINT32 MipiHsi1Len; // 652 + + UINT8 SdCardRemovable; // 656 reserve offset upto 658 + UINT8 HideLPSSDevices; // 657 Hide unsupported LPSS devices when in ACPI mode + UINT8 ReservedO; // 658 OS Selection + UINT8 Reserved00; // 659 + UINT8 Reserved01; // 660 + UINT8 Reserved02; // 661 + UINT8 Reserved03; // 662 + UINT8 Reserved04; // 663 + UINT8 Reserved05; // 664 + UINT8 Reserved06; // 665 + UINT8 Reserved07; // 666 + UINT8 Reserved08; // 667 + UINT8 Reserved09; // 668 + UINT8 Reserved0A; // 669 + UINT32 Reserved0B; // 670 + UINT32 Reserved0C; // 674 + UINT32 Reserved0D; // 678 + UINT32 Reserved0E; // 682 + UINT32 Reserved0F; // 686 + UINT32 Reserved10; // 690 + UINT32 Reserved11; // 694 + UINT32 Reserved12; // 698 + UINT32 Reserved13; // 702 + UINT32 Reserved14; // 706 + UINT32 Reserved15; // 710 + UINT32 Reserved16; // 714 + UINT8 Reserved17; + UINT32 Reserved18; + UINT32 Reserved19; + UINT32 Reserved1A; + UINT32 Reserved1B; + UINT32 Reserved1C; + UINT8 Reserved1D; + UINT32 Reserved1E; + UINT32 Reserved1F; + UINT32 Reserved20; + UINT32 Reserved21; + UINT32 Reserved22; + UINT8 Reserved23; + UINT8 BatteryChargingSolution; // 761 0-non ULPMC 1-ULPMC + + // + //101 bytes + // + UINT8 NFCnSelect; // 762 NFCx Select 1: NFC1 2:NFC2 + UINT8 LpssSccMode; // 763 EMMC device 0-ACPI mode, 1-PCI mode + + UINT32 TPMAddress; // 764 + UINT32 TPMLength; // 768 + + UINT8 I2CTouchAddress; // 772 I2C touch address, 0x4B:RVP 0x4A:FFRD + UINT8 IdleReserve; // 773 0 - disabled 1 - enabled + UINT8 SDIOMode; // 774 3 - Default 2 - DDR50 + UINT8 emmcVersion; // 775 0 - 4.41 1 - 4.5 + UINT32 BmBound; // 776 BM Bound + UINT8 FsaStatus; // 780 0 - Fsa is off, 1- Fsa is on + + // + // Board Id + // This field is for the ASL code to know whether this board is Baylake or Bayley Bay etc + // + UINT8 BoardID; // 781 + UINT8 FabID; // 782 + UINT8 OtgMode; // 783 0- OTG disable 1- OTG PCI mode + UINT8 Stepping; // 784 Stepping + UINT8 WittEnable; // 785 WITT eanble 0 - disable 1 - enable + + UINT8 SocStepping; // 786 Soc Stepping infomation + UINT8 AmbientTripPointChange; // 787 DPTF: Controls whether _ATI changes other participant's trip point(enabled/disabled) + UINT8 UtsEnable; // 788 Uart Test eanble 0 - disable 1 - enable + UINT8 DptfReserve; // 789 + + UINT8 SarEnable; // 790 + UINT8 PssDeveice; // 791 PSS Deveice: 0 - None, 1 - Monzax 2K, 2 - Monzax 8K + UINT8 EDPV; // 792 Check for eDP display device + UINT32 DIDX; // 793 Device ID for eDP device + UINT8 MicrosoftIoT; // (794)JP1 pins are for Microsoft IoT project. +} EFI_GLOBAL_NVS_AREA; +#pragma pack () + +// +// Global NVS Area Protocol +// +typedef struct _EFI_GLOBAL_NVS_AREA_PROTOCOL { + EFI_GLOBAL_NVS_AREA *Area; +} EFI_GLOBAL_NVS_AREA_PROTOCOL; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/HwWatchdogTimer.h b/Vlv2TbltDevicePkg/Include/Protocol/HwWatchdogTimer.h new file mode 100644 index 0000000000..75c707162f --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/HwWatchdogTimer.h @@ -0,0 +1,240 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + HwWatchdogTimer.h + +Abstract: + + +--*/ + +#ifndef __EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL_H__ +#define __EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL_H__ + +#define EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL_GUID \ + { 0xd5b06d16, 0x2ea1, 0x4def, 0x98, 0xd0, 0xa0, 0x5d, 0x40, 0x72, 0x84, 0x17 } + +#define EFI_WATCHDOG_TIMER_NOT_SUPPORTED_PROTOCOL_GUID \ + { 0xe9e156ac, 0x3203, 0x4572, 0xac, 0xdf, 0x84, 0x4f, 0xdc, 0xdb, 0x6, 0xbf } + + +#include + +// +// General Purpose Constants +// +#define ICH_INSTAFLUSH_GPIO BIT16 // BIT 16 in GPIO Level 2 is GPIO 48. +#define B_INSTAFLUSH BIT4 + +// +// Other Watchdog timer values +// +#define WDT_COUNTDOWN_VALUE 0x14 +#define BDS_WDT_COUNTDOWN_VALUE 0x35 + +// +// Prototypes for the Watchdog Timer Driver Protocol +// + +/** + This service begins the Watchdog Timer countdown. If the countdown completes prior to + Stop Timer or Restart Timer the system will reset. + + @param[in] None + + @retval EFI_SUCCESS Operation completed successfully + @retval EFI_DEVICE_ERROR The command was unsuccessful + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_START_TIMER) ( + VOID + ); + +/** + This service resets the Watchdog Timer countdown and should only be called after the + Start Timer function. + + @param[in] None + + @retval EFI_SUCCESS Operation completed successfully + @retval EFI_DEVICE_ERROR The command was unsuccessful + +**/ +typedef +EFI_STATUS +(EFIAPI *PEI_WATCHDOG_RESET_TIMER) ( + VOID + ); + +/** + This service restarts the Watchdog Timer countdown and should only be called after the + Start Timer function. + + @param[in] None + + @retval EFI_SUCCESS Operation completed successfully + @retval EFI_DEVICE_ERROR The command was unsuccessful + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_RESTART_TIMER) ( + VOID + ); + +/** + This service disables the Watchdog Timer countdown. + + @param[in] None + + @retval EFI_SUCCESS Operation completed successfully + @retval EFI_DEVICE_ERROR The command was unsuccessful + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_STOP_TIMER) ( + VOID + ); + +/** + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_CHECK_TIMEOUT) ( + OUT HW_WATCHDOG_TIMEOUT *WatchdogTimeout + ); + + + +/** + This service forces a reboot of the system due to a reset of the POWERGOOD_PS, + POWERGOOD_CLK, and the BSEL Override + + Arguments: + None + + Returns: + This function should not return! + + EFI_DEVICE_ERROR - The command was unsuccessful and a reboot did not occur + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_FORCE_REBOOT) ( + IN BOOLEAN ForceTimeout, + IN UINT8 ResetType + ); + +/** + This service notifies the Watchdog Timer of the fact that a known reset is occuring. + + @param[in] AllowReset TRUE if a Reset is currently expected + FALSE if a Reset is not currently expected + + This function should not return! + + EFI_DEVICE_ERROR - The command was unsuccessful and a reboot did not occur + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_KNOWN_RESET) ( + IN BOOLEAN AllowReset + ); + +/** + This service reads the current Watchdog Timer countdown reload value. + + @param[in] CountdownValue pointer to UINT32 to return the value of the reload register. + + @retval EFI_SUCCESS Operation completed successfully + @retval EFI_DEVICE_ERROR The command was unsuccessful + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_TIMER_COUNT_DOWN_PERIOD)( + OUT UINT32 *CountdownValue + ); + +/** + This service reads the current Watchdog Timer countdown reload value. + + @param[in] CountdownValue Value to set the reload register. + + @retval EFI_SUCCESS Operation completed successfully + @retval EFI_DEVICE_ERROR The command was unsuccessful + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_TIMER_COUNT_DOWN_PERIOD)( + OUT UINT32 CountdownValue + ); + +/** + This service clears the state that indicates the Watchdog Timer fired. + + @retval EFI_SUCCESS - Operation completed successfully + @retval EFI_DEVICE_ERROR - The command was unsuccessful + +**/ +typedef +EFI_STATUS +(EFIAPI *PEI_WATCHDOG_CLEAR_TIMER_STATE) ( + ); + +/** + This service disables the Watchdog Timer countdown. It also closes the recurring restart event + if the event exists. + + @param[in] Stall TRUE = Stop the timer countdown + FALSE = Start the timer countdown + + @retval EFI_SUCCESS Operation completed successfully + @retval EFI_DEVICE_ERROR The command was unsuccessful + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_STALL_WATCHDOG_COUNTDOWN) ( + IN BOOLEAN Stall + ); + + +typedef struct _EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL { + EFI_WATCHDOG_START_TIMER StartWatchdogTimer; + PEI_WATCHDOG_RESET_TIMER ResetWatchdogTimeout; + EFI_WATCHDOG_RESTART_TIMER RestartWatchdogTimer; + EFI_WATCHDOG_STOP_TIMER StopWatchdogTimer; + EFI_WATCHDOG_CHECK_TIMEOUT CheckWatchdogTimeout; + EFI_WATCHDOG_FORCE_REBOOT ForceReboot; + EFI_WATCHDOG_KNOWN_RESET AllowKnownReset; + EFI_GET_TIMER_COUNT_DOWN_PERIOD GetCountdownPeriod; + EFI_SET_TIMER_COUNT_DOWN_PERIOD SetCountdownPeriod; + PEI_WATCHDOG_CLEAR_TIMER_STATE ClearTimerState; + EFI_STALL_WATCHDOG_COUNTDOWN StallWatchdogCountdown; +} EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL; + +extern EFI_GUID gEfiWatchdogTimerDriverProtocolGuid; +extern EFI_GUID gEfiWatchdogTimerNotSupportedProtocolGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/I2cAcpi.h b/Vlv2TbltDevicePkg/Include/Protocol/I2cAcpi.h new file mode 100644 index 0000000000..14a0b7079e --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/I2cAcpi.h @@ -0,0 +1,112 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +**/ + +#ifndef __I2C_ACPI_H__ +#define __I2C_ACPI_H__ + +#include + +// +// I2C ACPI protocol +// +typedef struct _EFI_I2C_ACPI_PROTOCOL EFI_I2C_ACPI_PROTOCOL; + +// +// I2C device description +// +// This structure provides the platform specific information which +// describes an I2C device. +// +typedef struct { + // + // Hardware revision - ACPI _HRV value + // + UINT32 HardwareRevision; + + // + // Device path node for the I2C device. + // + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // I2C bus configuration for the I2C device. + // + UINT32 I2cBusConfiguration; + + // + // Number of slave addresses for the I2C device. + // + UINT32 SlaveAddressCount; + + // + // Address of the array of slave addresses for the I2C device. + // + CONST UINT32 *SlaveAddressArray; +}EFI_I2C_DEVICE; + + +/** + Enumerate the I2C devices + + This routine must be called at or below TPL_NOTIFY. + + This function walks the platform specific data to enumerates the + I2C devices on an I2C bus. + + @param[in] This Address of an EFI_I2C_ENUM_PROTOCOL + structure. + @param[in, out] Device Buffer containing the address of an + EFI_I2C_DEVICE structure. Enumeration + is started by setting the initial + EFI_I2C_DEVICE structure address to NULL. + The buffer receives an EFI_I2C_DEVICE + structure address for the next I2C device. + + @retval EFI_SUCCESS The platform data for the next device + on the I2C bus was returned successfully. + @retval EFI_INVALID_PARAMETER NextDevice was NULL + @retval EFI_NO_MAPPING PreviousDevice does not point to a valid + EFI_I2C_DEVICE structure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_ACPI_ENUMERATE) ( + IN CONST EFI_I2C_ACPI_PROTOCOL *This, + IN OUT CONST EFI_I2C_DEVICE **Device + ); + +// +// I2C device description +// +// This structure provides the platform specific information which +// describes an I2C device. +// +struct _EFI_I2C_ACPI_PROTOCOL { + // + // Walk the platform's list of I2C devices on the bus. This + // routine returns the next I2C device in the platform's list + // for this I2C bus. + // + EFI_I2C_ACPI_ENUMERATE Enumerate; +}; + +// +// Variable containing the GUID for the I2C device enumeration protocol +// +extern EFI_GUID gEfiI2cAcpiProtocolGuid; + +#endif // __I2C_ACPI_H__ diff --git a/Vlv2TbltDevicePkg/Include/Protocol/I2cBus.h b/Vlv2TbltDevicePkg/Include/Protocol/I2cBus.h new file mode 100644 index 0000000000..d32837a921 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/I2cBus.h @@ -0,0 +1,169 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef __I2C_BUS_H__ +#define __I2C_BUS_H__ + +#include + +// +// I2C bus protocol +// +typedef struct _EFI_I2C_BUS_PROTOCOL EFI_I2C_BUS_PROTOCOL; + + +/** + Perform an I2C operation on the device + + This routine must be called at or below TPL_NOTIFY. For synchronous + requests this routine must be called at or below TPL_CALLBACK. + + N.B. The typical consumers of this API are the third party I2C + drivers. Extreme care must be taken by other consumers of this + API to prevent confusing the third party I2C drivers due to a + state change at the I2C device which the third party I2C drivers + did not initiate. I2C platform drivers may use this API within + these guidelines. + + This routine queues an operation to the I2C controller for execution + on the I2C bus. + + As an upper layer driver writer, the following need to be provided + to the platform vendor: + + 1. ACPI CID value or string - this is used to connect the upper layer + driver to the device. + 2. Slave address array guidance when the I2C device uses more than one + slave address. This is used to access the blocks of hardware within + the I2C device. + + @param[in] This Address of an EFI_I2C_BUS_PROTOCOL + structure + @param[in] SlaveAddressIndex Index into an array of slave addresses for + the I2C device. The values in the array are + specified by the board designer, with the + I2C device driver writer providing the slave + address order. + + For devices that have a single slave address, + this value must be zero. If the I2C device + uses more than one slave address then the third + party (upper level) I2C driver writer needs to + specify the order of entries in the slave address + array. + + \ref ThirdPartyI2cDrivers "Third Party I2C Drivers" + section in I2cMaster.h. + @param[in] Event Event to set for asynchronous operations, + NULL for synchronous operations + @param[in] RequestPacket Address of an EFI_I2C_REQUEST_PACKET + structure describing the I2C operation + @param[out] I2cStatus Optional buffer to receive the I2C operation + completion status + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_ABORTED The request did not complete because the driver + was shutdown. + @retval EFI_ACCESS_DENIED Invalid SlaveAddressIndex value + @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large. + @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation. + This could indicate the slave device is not present. + @retval EFI_INVALID_PARAMETER RequestPacket is NULL + @retval EFI_INVALID_PARAMETER TPL is too high + @retval EFI_NO_RESPONSE The I2C device is not responding to the + slave address. EFI_DEVICE_ERROR may also be + returned if the controller can not distinguish + when the NACK occurred. + @retval EFI_NOT_FOUND I2C slave address exceeds maximum address + @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for + the event and then read status pointed to by + the request packet. + @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation + @retval EFI_TIMEOUT The transaction did not complete within an internally + specified timeout period. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_BUS_START_REQUEST) ( + IN CONST EFI_I2C_BUS_PROTOCOL *This, + IN UINTN SlaveAddressIndex, + IN EFI_EVENT Event OPTIONAL, + IN CONST EFI_I2C_REQUEST_PACKET *RequestPacket, + OUT EFI_STATUS *I2cStatus OPTIONAL + ); + +// +// The I2C bus protocol enables access to a specific device on the I2C bus. +// +// Each I2C device is described as an ACPI node (HID, UID and CID) within the +// platform layer. The I2C bus protocol enumerates the I2C devices in the +// platform and creates a unique handle and device path for each I2C device. +// +// I2C slave addressing is abstracted to validate addresses and limit operation +// to the specified I2C device. The third party providing the I2C device support +// provides an ordered list of slave addresses for the I2C device to the team +// building the platform layer. The platform team must preserve the order of the +// supplied list. SlaveAddressCount is the number of entries in this list or +// array within the platform layer. The third party device support references +// a slave address using an index into the list or array in the range of zero +// to SlaveAddressCount - 1. +// +struct _EFI_I2C_BUS_PROTOCOL { + // + // Start an I2C operation on the bus + // + EFI_I2C_BUS_START_REQUEST StartRequest; + + // + // The maximum number of slave addresses for the I2C device. The caller may + // validate this value as a check on the platform layer's configuration. Slave + // address selection uses an index value in the range of zero to SlaveAddressCount - 1. + // + UINTN SlaveAddressCount; + + // + // Hardware revision - Matches the ACPI _HRV value + // + // The HardwareRevision value allows a single driver to support multiple hardware + // revisions and implement the necessary workarounds for limitations within the + // hardware. + // + UINT32 HardwareRevision; + + // + // The maximum number of bytes the I2C host controller + // is able to receive from the I2C bus. + // + UINT32 MaximumReceiveBytes; + + // + // The maximum number of bytes the I2C host controller + // is able to send on the I2C bus. + // + UINT32 MaximumTransmitBytes; + + // + // The maximum number of bytes in the I2C bus transaction. + // + UINT32 MaximumTotalBytes; +}; + +// +// GUID for the I2C bus protocol +// +extern EFI_GUID gEfiI2cBusProtocolGuid; + +#endif // __I2C_BUS_H__ diff --git a/Vlv2TbltDevicePkg/Include/Protocol/I2cBusMcg.h b/Vlv2TbltDevicePkg/Include/Protocol/I2cBusMcg.h new file mode 100644 index 0000000000..0fcadd5d2e --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/I2cBusMcg.h @@ -0,0 +1,168 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef __I2C_BUS_H__ +#define __I2C_BUS_H__ + +#include + +// +// I2C bus protocol +// +typedef struct _EFI_I2C_BUS_PROTOCOL EFI_I2C_BUS_PROTOCOL; + +/** + Perform an I2C operation on the device + + This routine must be called at or below TPL_NOTIFY. For synchronous + requests this routine must be called at or below TPL_CALLBACK. + + N.B. The typical consumers of this API are the third party I2C + drivers. Extreme care must be taken by other consumers of this + API to prevent confusing the third party I2C drivers due to a + state change at the I2C device which the third party I2C drivers + did not initiate. I2C platform drivers may use this API within + these guidelines. + + This routine queues an operation to the I2C controller for execution + on the I2C bus. + + As an upper layer driver writer, the following need to be provided + to the platform vendor: + + 1. ACPI CID value or string - this is used to connect the upper layer + driver to the device. + 2. Slave address array guidance when the I2C device uses more than one + slave address. This is used to access the blocks of hardware within + the I2C device. + + @param[in] This Address of an EFI_I2C_BUS_PROTOCOL + structure + @param[in] SlaveAddressIndex Index into an array of slave addresses for + the I2C device. The values in the array are + specified by the board designer, with the + I2C device driver writer providing the slave + address order. + + For devices that have a single slave address, + this value must be zero. If the I2C device + uses more than one slave address then the third + party (upper level) I2C driver writer needs to + specify the order of entries in the slave address + array. + + \ref ThirdPartyI2cDrivers "Third Party I2C Drivers" + section in I2cMaster.h. + @param[in] Event Event to set for asynchronous operations, + NULL for synchronous operations + @param[in] RequestPacket Address of an EFI_I2C_REQUEST_PACKET + structure describing the I2C operation + @param[out] I2cStatus Optional buffer to receive the I2C operation + completion status + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_ABORTED The request did not complete because the driver + was shutdown. + @retval EFI_ACCESS_DENIED Invalid SlaveAddressIndex value + @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large. + @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation. + This could indicate the slave device is not present. + @retval EFI_INVALID_PARAMETER RequestPacket is NULL + @retval EFI_INVALID_PARAMETER TPL is too high + @retval EFI_NO_RESPONSE The I2C device is not responding to the + slave address. EFI_DEVICE_ERROR may also be + returned if the controller can not distinguish + when the NACK occurred. + @retval EFI_NOT_FOUND I2C slave address exceeds maximum address + @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for + the event and then read status pointed to by + the request packet. + @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation + @retval EFI_TIMEOUT The transaction did not complete within an internally + specified timeout period. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_BUS_START_REQUEST) ( + IN CONST EFI_I2C_BUS_PROTOCOL *This, + IN UINTN SlaveAddressIndex, + IN EFI_EVENT Event OPTIONAL, + IN CONST EFI_I2C_REQUEST_PACKET *RequestPacket, + OUT EFI_STATUS *I2cStatus OPTIONAL + ); + +// +// The I2C bus protocol enables access to a specific device on the I2C bus. +// +// Each I2C device is described as an ACPI node (HID, UID and CID) within the +// platform layer. The I2C bus protocol enumerates the I2C devices in the +// platform and creates a unique handle and device path for each I2C device. +// +// I2C slave addressing is abstracted to validate addresses and limit operation +// to the specified I2C device. The third party providing the I2C device support +// provides an ordered list of slave addresses for the I2C device to the team +// building the platform layer. The platform team must preserve the order of the +// supplied list. SlaveAddressCount is the number of entries in this list or +// array within the platform layer. The third party device support references +// a slave address using an index into the list or array in the range of zero +// to SlaveAddressCount - 1. +// +struct _EFI_I2C_BUS_PROTOCOL { + // + // Start an I2C operation on the bus + // + EFI_I2C_BUS_START_REQUEST StartRequest; + + // + // The maximum number of slave addresses for the I2C device. The caller may + // validate this value as a check on the platform layer's configuration. Slave + // address selection uses an index value in the range of zero to SlaveAddressCount - 1. + // + UINTN SlaveAddressCount; + + // + // Hardware revision - Matches the ACPI _HRV value + // + // The HardwareRevision value allows a single driver to support multiple hardware + // revisions and implement the necessary workarounds for limitations within the + // hardware. + // + UINT32 HardwareRevision; + + // + // The maximum number of bytes the I2C host controller + // is able to receive from the I2C bus. + /// + UINT32 MaximumReceiveBytes; + + // + // The maximum number of bytes the I2C host controller + // is able to send on the I2C bus. + // + UINT32 MaximumTransmitBytes; + + // + // The maximum number of bytes in the I2C bus transaction. + // + UINT32 MaximumTotalBytes; +}; + +// +// GUID for the I2C bus protocol +// +extern EFI_GUID gEfiI2cBusProtocolGuid; + +#endif // __I2C_BUS_H__ diff --git a/Vlv2TbltDevicePkg/Include/Protocol/I2cHostMcg.h b/Vlv2TbltDevicePkg/Include/Protocol/I2cHostMcg.h new file mode 100644 index 0000000000..3395043d3e --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/I2cHostMcg.h @@ -0,0 +1,143 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef __I2C_HOST_H__ +#define __I2C_HOST_H__ + +#include + +/** + Declare the forward references + +**/ +typedef struct _EFI_I2C_HOST_PROTOCOL EFI_I2C_HOST_PROTOCOL; +typedef struct _EFI_I2C_HOST_CALLBACKS EFI_I2C_HOST_CALLBACKS; + + +/** + Queue an I2C operation for execution on the I2C controller. + + This routine must be called at or below TPL_NOTIFY. For synchronous + requests this routine must be called at or below TPL_CALLBACK. + + N.B. The typical consumers of this API are the I2C bus driver and + on rare occasions the I2C test application. Extreme care must be + taken by other consumers of this API to prevent confusing the + third party I2C drivers due to a state change at the I2C device + which the third party I2C drivers did not initiate. I2C platform + drivers may use this API within these guidelines. + + This layer uses the concept of I2C bus configurations to describe + the I2C bus. An I2C bus configuration is defined as a unique + setting of the multiplexers and switches in the I2C bus which + enable access to one or more I2C devices. When using a switch + to divide a bus, due to speed differences, the I2C platform layer + would define an I2C bus configuration for the I2C devices on each + side of the switch. When using a multiplexer, the I2C platform + layer defines an I2C bus configuration for each of the selector + values required to control the multiplexer. See Figure 1 in the +
I2C + Specification for a complex I2C bus configuration. + + The I2C host driver processes all operations in FIFO order. Prior to + performing the operation, the I2C host driver calls the I2C platform + driver to reconfigure the switches and multiplexers in the I2C bus + enabling access to the specified I2C device. The I2C platform driver + also selects the maximum bus speed for the device. After the I2C bus + is configured, the I2C host driver calls the I2C port driver to + initialize the I2C controller and start the I2C operation. + + @param[in] This Address of an EFI_I2C_HOST_PROTOCOL instance. + @param[in] I2cBusConfiguration I2C bus configuration to access the I2C + device. + @param[in] SlaveAddress Address of the device on the I2C bus. + @param[in] Event Event to set for asynchronous operations, + NULL for synchronous operations + @param[in] RequestPacket Address of an EFI_I2C_REQUEST_PACKET + structure describing the I2C operation + @param[out] I2cStatus Optional buffer to receive the I2C operation + completion status + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_ABORTED The request did not complete because the driver + was shutdown. + @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large. + @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation. + This could indicate the slave device is not present. + @retval EFI_INVALID_PARAMETER RequestPacket is NULL + @retval EFI_INVALID_PARAMETER TPL is too high + @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value + @retval EFI_NO_RESPONSE The I2C device is not responding to the + slave address. EFI_DEVICE_ERROR may also be + returned if the controller cannot distinguish + when the NACK occurred. + @retval EFI_NOT_FOUND I2C slave address exceeds maximum address + @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for + the event and then read status pointed to by + the request packet. + @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation + @retval EFI_TIMEOUT The transaction did not complete within an internally + specified timeout period. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_HOST_QUEUE_REQUEST) ( + IN CONST EFI_I2C_HOST_PROTOCOL *This, + IN UINTN I2cBusConfiguration, + IN UINTN SlaveAddress, + IN EFI_EVENT Event OPTIONAL, + IN CONST EFI_I2C_REQUEST_PACKET *RequestPacket, + OUT EFI_STATUS *I2cStatus OPTIONAL + ); + +/// +/// Host access to the I2C bus. +/// +struct _EFI_I2C_HOST_PROTOCOL { + /// + /// Queue an operation for execution on the I2C bus + /// + EFI_I2C_HOST_QUEUE_REQUEST QueueRequest; + + /// + /// The maximum number of I2C bus configurations + /// + UINTN I2cBusConfigurationCount; + + /// + /// The maximum number of bytes the I2C host controller + /// is able to receive from the I2C bus. + /// + UINT32 MaximumReceiveBytes; + + /// + /// The maximum number of bytes the I2C host controller + /// is able to send on the I2C bus. + /// + UINT32 MaximumTransmitBytes; + + /// + /// The maximum number of bytes in the I2C bus transaction. + /// + UINT32 MaximumTotalBytes; +}; + +/// +/// GUID for the EFI_I2C_HOST_PROTOCOL +/// +extern EFI_GUID gEfiI2cHostProtocolGuid; + +#endif // __I2C_HOST_H__ diff --git a/Vlv2TbltDevicePkg/Include/Protocol/I2cMasterMcg.h b/Vlv2TbltDevicePkg/Include/Protocol/I2cMasterMcg.h new file mode 100644 index 0000000000..f239b5ec2f --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/I2cMasterMcg.h @@ -0,0 +1,524 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + \section I2cDriverStack I2C Driver Stack + + The following is a representation of the I2C (I2C) + driver stack and an I2C bus layout. + +

+              +-----------------+
+              |   Application   |
+              +-----------------+
+                       |
+                       | Third Party or UEFI
+                       |
+                       V
+ +--------+   +-----------------+
+ | Slave  |   |   Third Party   |
+ | Driver |   |   I2C Device    |
+ |        |   |     Driver      |
+ +--------+   +-----------------+
+      |                |
+      |          BUS   |
+      |                |
+      |                V
+      |       +-----------------+
+      |       | I2C Bus Driver  |------------------.
+      |       +-----------------+                  |
+      |                |                           |
+      |         HOST   |          BUS              |
+      |                |          CONFIGURATION    |
+SLAVE |                V          MANAGEMENT       | ACPI
+      |       +-----------------+                  |
+      |       | I2C Host Driver |----------.       |
+      |       +-----------------+          |       |
+      |                |                   |       |
+      |        MASTER  |                   V       V
+      |                |               +-------=-------------+
+      |                V               | I2C Platform Driver |
+      |       +-----------------+      +---------------------+
+      `------>| I2C Port Driver |               |      |
+              +-----------------+               |      |
+                       |                        |      |
+            Software   |                        |      |
+            --------------------------------------------------
+            Hardware   |                        |      |
+                       |                        |      |
+                       V                        |      |
+              +-----------------+               |      |
+              | I2C Controller  |               |      |
+              +-----------------+               |      |
+                       |                        |      |
+            -----------------------             |      |
+            I2C Bus    |                        |      |
+                       |    +------------+      |      |
+                       +----| High speed |      |      |
+                       |    | I2C device |      |      |
+                       |    |    0x01    |      |      |
+                       |    +------------+      |      |
+                       |                        |      |
+                  +---------+  0                |      |
+                  | Switch  |<------------------`      |
+                  +---------+  1                       |
+                       |                               |
+                       |    +------------+             |
+                       +----| Fast speed |             |
+                       |    | I2C device |             |
+                       |    |    0x02    |             |
+                       |    +------------+             |
+                       |                               |
+                +-------------+                        |
+                | Multiplexer |<-----------------------`
+                +-------------+
+                 0 |       | 1
+                   |       |
+                   |       |
+                   |       |    +-------------+
+                   |       +----| Third Party |
+                   |       |    | I2C Device  |
+                   |       |    |  0x03, 0x04 |
+                   |       |    +-------------+
+                   |       |
+                   |
+                   |            +-------------+
+                   +------------| Third Party |
+                   |            | I2C Device  |
+                   |            |  0x03, 0x04 |
+                   |            +-------------+
+                   |
+  
+ + The platform hardware designer chooses the bus layout based upon + the platform, I2C chip and software requirements. The design uses + switches to truncate the bus to enable higher speed operation for a + subset of devices which are placed closer to the controller. When the + switch is on, the extended bus must operate at a lower speed. The + design uses multiplexer to create separate address spaces enabling + the use of multiple devices which would otherwise have conflicting + addresses. See the + I2C + Specification for more details. + + N.B. Some operating systems may prohibit the changing of switches + and multiplexers in the I2C bus. In this case the platform hardware + and software designers must select a single I2C bus configuration + consisting of constant input values for the switches and multiplexers. + The platform software designer must then ensure that this I2C bus + configuration is enabled prior to passing control to the operating + system. + + The platform hardware designer needs to provide the platform software + designer the following data for each I2C bus: + + 1. Which controller controls this bus + + 2. A list of logic blocks contained in one or more I2C devices: + + a. I2C device which contains this logic block + + b. Logic block slave address + + c. Logic block name + + 3. For each configuration of the switches and multiplexer + + a. What is the maximum speed of operation + + b. What devices are accessible + + 4. The settings for the switches and multiplexers when control is + given to the operating system. + + \section ThirdPartyI2cDrivers Third Party I2C Drivers + + This layer is I2C chip specific but platform and host controller + independent. + + Third party I2C driver writers, typically silicon vendors, need + to provide: + + 1. The device path node data that is used to select their + driver. + + 2. The order for the blocks of logic that get referenced + by the entries in the slave address array. + + 3. The hardware version of the I2C device, this value is passed + to the third party I2C driver to enable it to perform work + arounds for the specific hardware version. This value should + match the value in the ACPI _HRV tag. + + The third party I2C driver uses relative addressing to abstract + the platform specific details of the I2C device. Using an + example I2C device containing an accelerometer and a magnetometer + which consumes two slave addresses, one for each logic block. The + third party I2C driver writer may choose to write two drivers, one + for each block of logic, in which case each driver refers to the + single I2C slave address using the relative value of zero (0). + However if the third party I2C driver writer chooses to write a + single driver which consumes multiple slave addresses then the + third party I2C driver writer needs to convey the order of the + I2C slave address entries in the slave address array to the + platform software designer. For the example: + + 0: Accelerometer + + 1: Magnetometer + + The platform hardware designer picks the actual slave addresses + from the I2C device's data sheet and provides this information + to the platform software designer. The platform software designer + then places the slave addresses into the slave address array in the + order specified by the third party I2C driver writer. The third + party driver I2C writer then indirectly references this array by + specifying the index value as the relative slave address. The + relative value always starts at zero (0) and its maximum value is + the number of entries in slave address array minus one. + + The slave address is specified as a 32-bit integer to allow room + for future slave address expansion. Only the port driver knows + the maximum slave address value. All other drivers and + applications must look for the EFI_NOT_FOUND status for the + indication that the maximum slave address was exceeded. + + \section I2cBusDriver I2C Bus Driver + + This layer is platform, host controller, and I2C chip independent. + + The I2C bus driver creates a handle for each of the I2C devices + described within the platform driver. The I2C controller's device + path is extended with the device path node provided by the platform + driver and attached to the handle. The third party I2C device driver + uses the device path to determine if it may connect. For ACPI nodes, + the third party I2C driver should use the CID or CidString value. + + The I2C bus driver validates the relative address for the I2C device + and then converts the relative value to an actual I2C slave address. + The request is then passed to the I2C host driver. + + \section I2cHostDriver I2C Host Driver + + This layer is platform, host controller, and I2C chip independent. + + N.B. For proper operation of the I2C bus, only the I2C bus driver + and the I2C test application should connect to the I2C host driver + via the EFI_I2C_HOST_DRIVER_PROTOCOL. + + The I2C host driver may access any device on the I2C bus. The I2C + host driver has the following responsibilities: + + 1. Limits the number of requests to the I2C port driver to one. + The I2C host driver holds on to additional requests until the + I2C port driver is available to process the request. The I2C + requests are issued in FIFO order to the I2C port driver. + + 2. Enable the proper I2C bus configuration before starting the + I2C request on the I2C port driver + + I2C devices are addressed as the tuple: BusConfiguration:SlaveAddress. + I2C bus configuration zero (0) is the portion of the I2C bus that + connects to the host controller. The bus configuration specifies + the control values for the switches and multiplexers in the I2C bus. + After the switches and multiplexers are properly configured, the I2C + controller uses the slave address to access the requested I2C device. + + Since the I2C driver stack supports asynchronous operations this + layer maintains a queue of I2C requests until the I2C controller + is available them. When a request reaches the head of the queue + the necessary bus configuration is enabled and then the request + is sent to the I2C port driver. + + \section I2cPortDriver I2C Port Driver + + This layer is I2C controller specific but platform independent. + + This layer manipulates the I2C controller to perform an operation + on the I2C bus. This layer does not configure the I2C bus so it + is up to the caller to ensure that the I2C bus is in the proper + configuration before issuing the I2C request. + + This layer typically needs the following information: + + 1. Host controller address + 2. Controller's input clock frequency + + Depending upon the I2C controller, more data may be necessary. + This layer may use any method to get these values: hard coded + values, PCD values, or may choose to communicate with the platform + layer using an undefined mechanism to get these values. + + If the I2C port driver requires data from the platform driver then + the I2C port driver writer needs to provide the platform interface + details to the platform software designer. + + \section I2cPlatformDriver I2C Platform Driver + + When enabling access to I2C devices within UEFI, this driver + installs the EFI_I2C_ACPI_PROTOCOL to provide the I2C device + descriptions to the I2C bus driver using the EFI_I2C_DEVICE + structure. These descriptions include the bus configuration + number required for the I2C device, the slave address array + and the device path. + + The EFI_I2C_BUS_CONFIGURATION_MANAGEMENT protocol is optional. + This protocol needs to be specified under the following conditions: + + 1. The I2C bus must operate at a frequency greater than 100 KHz + 2. The I2C bus contains switches or multiplexers. + + The EFI_I2C_BUS_CONFIGURATION_MANAGEMENT protocol enables the + I2C host driver to call into the I2C platform driver to enable + a specific I2C bus configuration and set its maximum clock speed. + + The platform software designer collects the data requirements + from third party I2C driver writers, the I2C controller + driver writer, the EFI_I2C_ACPI_PROTOCOL and + EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL. The platform + software designer gets the necessary data from the platform + hardware designer. The platform software designer then builds + the data structures and implements the necessary routines to + construct the I2C platform driver. + + \section I2cSwitches Switches and Multiplexers + + There are some I2C switches and I2C multiplexers where the control + is done via I2C commands. When the control inputs come via the + same I2C bus that is being configured then the platform driver must + use the EFI_I2C_MASTER_PROTOCOL that is passed to the platform + driver. While the I2C host driver makes the call to the I2C + platform driver to configure the bus, the host driver keeps the + I2C port driver idle, to allow the I2C platform driver preform + the necessary configuration operations. + + If however the configuration control is done via and I2C device + connected to a different I2C bus (host controller), then it is + possible for the platform software designer may choose between + the following: + + 1. Call into a third party I2C driver to manipulate the I2C + bus control device. + 2. Call into the EFI_I2C_BUS_PROTOCOL if no third party I2C + driver exists for the I2C bus control device + 3. Call into the EFI_I2C_HOST_PROTOCOL if the platform does + not expose the I2C bus control device. + +**/ + +#ifndef __I2C_MASTER_H__ +#define __I2C_MASTER_H__ + +/** + Declare the forward references + +**/ +typedef struct _EFI_I2C_MASTER_PROTOCOL EFI_I2C_MASTER_PROTOCOL; ///< I2C master protocol + +/// +/// I2C device operation +/// +/// This structure provides the information necessary for an operation +/// on an I2C device +/// +typedef struct { + /// + /// Number of bytes to send to the I2C device + /// + UINT32 WriteBytes; + + /// + /// Number of bytes to read, set to zero for write only operations + /// + UINT32 ReadBytes; + + /// + /// Address of the buffer containing the data to send to the I2C device. + /// The WriteBuffer must be at least WriteBytes in length. + /// + UINT8 *WriteBuffer; + + /// + /// Address of the buffer to receive data from the I2C device. Use NULL + /// for write only operations. The ReadBuffer must be at least ReadBytes + /// in length. + /// + UINT8 *ReadBuffer; + + /// + /// Timeout for the I2C operation in 100 ns units + /// + UINT32 Timeout; +} EFI_I2C_REQUEST_PACKET; + + +/** + Set the I2C controller bus clock frequency. + + This routine must be called at or below TPL_NOTIFY. + + The software and controller do a best case effort of using the specified + frequency for the I2C bus. If the frequency does not match exactly then + the controller will use a slightly lower frequency to avoid + exceeding the operating conditions for any of the I2C devices on the bus. + For example if 400 KHz was specified and the controller's divide network + only supports 402 KHz or 398 KHz then the controller would be set to 398 + KHz. However if the desired frequency is 400 KHz and the controller only + supports 1 MHz and 100 KHz then this routine would return EFI_UNSUPPORTED. + + @param[in] This Address of an EFI_I2C_MASTER_PROTOCOL + structure + @param[in] BusClockHertz New I2C bus clock frequency in Hertz + + @retval EFI_SUCCESS The bus frequency was set successfully. + @retval EFI_UNSUPPORTED The controller does not support this frequency. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_MASTER_BUS_FREQUENCY_SET) ( + IN CONST EFI_I2C_MASTER_PROTOCOL *This, + IN UINTN BusClockHertz + ); + +/** + Reset the I2C controller and configure it for use + + This routine must be called at or below TPL_NOTIFY. + + The I2C controller is reset and the I2C bus frequency is set to 100 KHz. + + @param[in] This Address of an EFI_I2C_MASTER_PROTOCOL + structure + +**/ +typedef +VOID +(EFIAPI *EFI_I2C_MASTER_RESET) ( + IN CONST EFI_I2C_MASTER_PROTOCOL *This + ); + +/** + Start an I2C operation on the host controller + + This routine must be called at or below TPL_NOTIFY. For synchronous + requests this routine must be called at or below TPL_CALLBACK. + + This function initiates an I2C operation on the controller. + + The operation is performed by selecting the I2C device with its slave + address and then sending all write data to the I2C device. If read data + is requested, a restart is sent followed by the slave address and then + the read data is clocked into the I2C controller and placed in the read + buffer. When the operation completes, the status value is returned and + then the event is set. + + N.B. The typical consumer of this API is the I2C host driver. + Extreme care must be taken by other consumers of this API to + prevent confusing the third party I2C drivers due to a state + change at the I2C device which the third party I2C drivers did + not initiate. I2C platform drivers may use this API within + these guidelines. + + N.B. This API supports only one operation, no queuing support + exists at this layer. This API assumes that the I2C bus is in + the correct configuration for the I2C request. + + @param[in] This Address of an EFI_I2C_MASTER_PROTOCOL + structure + @param[in] SlaveAddress Address of the device on the I2C bus. + @param[in] Event Event to set for asynchronous operations, + NULL for synchronous operations + @param[in] RequestPacket Address of an EFI_I2C_REQUEST_PACKET + structure describing the I2C operation + @param[out] I2cStatus Optional buffer to receive the I2C operation + completion status + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_ABORTED The request did not complete because the driver + was shutdown. + @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large. + @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation. + This could indicate the slave device is not present. + @retval EFI_INVALID_PARAMETER RequestPacket is NULL + @retval EFI_INVALID_PARAMETER TPL is too high + @retval EFI_NOT_FOUND SlaveAddress exceeds maximum address + @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for + the event and then read status pointed to by + the request packet. + @retval EFI_NO_RESPONSE The I2C device is not responding to the + slave address. EFI_DEVICE_ERROR may also be + returned if the controller cannot distinguish + when the NACK occurred. + @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation + @retval EFI_TIMEOUT The transaction did not complete within an internally + specified timeout period. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_MASTER_START_REQUEST) ( + IN CONST EFI_I2C_MASTER_PROTOCOL *This, + IN UINTN SlaveAddress, + IN EFI_EVENT Event OPTIONAL, + IN CONST EFI_I2C_REQUEST_PACKET *RequestPacket, + OUT EFI_STATUS *I2cStatus OPTIONAL + ); + +/// +/// I2C master mode protocol +/// +/// This protocol manipulates the I2C host controller to perform transactions as a +/// master on the I2C bus using the current state of any switches or multiplexers +/// in the I2C bus. +/// +struct _EFI_I2C_MASTER_PROTOCOL { + /// + /// Set the clock frequency for the I2C bus + /// + EFI_I2C_MASTER_BUS_FREQUENCY_SET BusFrequencySet; + + /// + /// Reset the I2C host controller + /// + EFI_I2C_MASTER_RESET Reset; + + /// + /// Start an I2C transaction in master mode on the host controller + /// + EFI_I2C_MASTER_START_REQUEST StartRequest; + + /// + /// The maximum number of bytes the I2C host controller + /// is able to receive from the I2C bus. + /// + UINT32 MaximumReceiveBytes; + + /// + /// The maximum number of bytes the I2C host controller + /// is able to send on the I2C bus. + /// + UINT32 MaximumTransmitBytes; + + /// + /// The maximum number of bytes in the I2C bus transaction. + /// + UINT32 MaximumTotalBytes; +}; + +/// +/// GUID for the EFI_I2C_MASTER_PROTOCOL +/// +extern EFI_GUID gEfiI2cMasterProtocolGuid; + +#endif // __I2C_MASTER_H__ diff --git a/Vlv2TbltDevicePkg/Include/Protocol/I2cSlave.h b/Vlv2TbltDevicePkg/Include/Protocol/I2cSlave.h new file mode 100644 index 0000000000..ba094ff807 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/I2cSlave.h @@ -0,0 +1,199 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +**/ + +#ifndef __I2C_SLAVE_H__ +#define __I2C_SLAVE_H__ + +#include + +/** + Declare the forward references + +**/ +typedef struct _EFI_I2C_SLAVE_PROTOCOL EFI_I2C_SLAVE_PROTOCOL; ///< I2C slave protocol + +/** + The I2C controller received a data byte from the + I2C msster. + + @param[in] Context The value passed to the slave enable routine. + @param[in] NumberOfBytes Number of data bytes received + @param[in] Data Buffer containing the received data bytes + + @retval EFI_SUCCESS ACK the data byte + @retval EFI_UNSUPPORTED NACK the data byte + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_SLAVE_RECEIVE_DATA) ( + IN VOID *Context, + IN UINTN NumberOfBytes, + IN CONST UINT8 *Data + ); + +/** + The I2C controller received the start bit from the + I2C master. + + @param[in] Context The value passed to the slave enable routine. + +**/ +typedef +VOID +(EFIAPI *EFI_I2C_SLAVE_RECEIVE_START) ( + IN VOID *Context, + IN UINTN BytesSent, + IN EFI_STATUS Status + ); + +/** + The I2C controller received the stop bit from the + I2C master. + + @param[in] Context The value passed to the slave enable routine. + @param[in] BytesSent Number of bytes successfully ACKed by the + I2C master. This is a hint, not all I2C + controllers support the ability to return + the number of bytes sent. When it is not + possible, the port driver returns zero. + @param[in] Status
    +
  • EFI_SUCCESS - All of the data was successfully sent
  • +
  • EFI_ABORTED - The controller was reset
  • +
  • EFI_DEVICE_ERROR - A NACK was received when sending the data.
  • +
  • EFI_END_OF_FILE - The stop bit was received before all of + the data was sent.
  • +
+ +**/ +typedef +VOID +(EFIAPI *EFI_I2C_SLAVE_RECEIVE_STOP) ( + IN VOID *Context, + IN UINTN BytesSent, + IN EFI_STATUS Status + ); + +/** + Enable or disable I2C slave operation. + + The ReceiveData callback allows the port driver to return data + to the driver or application handling slave mode operations. This + is data that a remote master has sent to the local I2C controller. + The data may be returned one byte at a time if the controller supports + the ability to ACK/NACK on each receive byte. If not, a block of + data may be returned by the I2C port driver and the ACK/NACK status + is used only as a hint for the port driver. + + The slave mode driver or application should buffer the data until + either ReceiveStart or ReceiveStop is called. At that time all of + the data is received and the command may be processed. + + ReceiveStart is called when the I2C master is expecting a response. + After processing the command, but before sending the response the + slave driver or application should mark the command as processed to + avoid processing it a second time when ReceiveStop is called. The + slave driver or application then calls SendData to send to queue the + response data for transmission. The data must remain valid in the + WriteBuffer until ReceiveStop is called. + + ReceiveStop is called when the stop bit is received on the I2C bus. + The slave driver or application starts processing the command if an + command data is pending in the slave driver's or application's buffer. + The BytesSent value is a hint to the slave driver or application as + to how much data was returned to the I2C master. If the controller + does not provide this level of support then this value is set to zero. + + @param[in] This Address of an EFI_I2C_SLAVE_PROTOCOL + structure + @param[in] SlaveAddress Slave address for the I2C controller + @param[in] Context Address of a context structure for use when + calling ReceiveData or ReceiveStop + @param[in] ReceiveData Called by the I2C port driver as data bytes + are received from the master. Response status + indicates if the byte is ACKed or NACKed. When + data is passed back a byte at a time, the port + driver must hold the clock until this callback + returns. + @param[in] ReceiveStart Called when the I2C controller receives a start bit. + @param[in] ReceiveStop Called after all of the data bytes are + received. + + @retval EFI_SUCCESS Slave operation is enabled on the controller. + @retval EFI_UNSUPPORTED The controller does not support this frequency. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_SLAVE_ENABLE) ( + IN CONST EFI_I2C_SLAVE_PROTOCOL *This, + IN UINT32 SlaveAddress, + IN VOID *Context, + IN EFI_I2C_SLAVE_RECEIVE_DATA ReceiveData, + IN EFI_I2C_SLAVE_RECEIVE_START ReceiveStart, + IN EFI_I2C_SLAVE_RECEIVE_STOP ReceiveStop + ); + +/** + Send data to the I2C master. + + Port drivers may implement this as a blocking or non-blocking call. + The data in the write buffer must remain valid until ReceiveStop or + ReceiveStart is called indicating that the I2C master has terminated + the transfer. + + @param[in] This Address of an EFI_I2C_SLAVE_PROTOCOL + structure + @param[in] WriteBytes Number of bytes to write + @param[in] WriteBuffer Buffer containing the data to send + + @retval EFI_SUCCESS Data waiting for master access. + @retval EFI_INVALID_PARAMETER WriteBuffer is NULL or WriteBytes + is zero. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_SLAVE_SEND) ( + IN CONST EFI_I2C_SLAVE_PROTOCOL *This, + IN UINTN WriteBytes, + IN CONST UINT8 *WriteBuffer + ); + +/// +/// I2C slave protocol +/// +/// The port driver publishes this protocol when slave mode is +/// supported by the controller. +/// +struct _EFI_I2C_SLAVE_PROTOCOL { + /// + /// Enable or disable I2C slave operation + /// + EFI_I2C_SLAVE_ENABLE SlaveEnable; + + /// + /// Send data to the I2C master + /// + EFI_I2C_SLAVE_SEND SendData; +}; + +/// +/// GUID for the EFI_I2C_SLAVE_PROTOCOL +/// +extern EFI_GUID gEfiI2cSlaveProtocolGuid; + +#endif // __I2C_SLAVE_H__ diff --git a/Vlv2TbltDevicePkg/Include/Protocol/LpcWpc83627Policy.h b/Vlv2TbltDevicePkg/Include/Protocol/LpcWpc83627Policy.h new file mode 100644 index 0000000000..d7b54bedf9 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/LpcWpc83627Policy.h @@ -0,0 +1,97 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + LpcWpc83667Policy.h + +Abstract: + + Protocol used for WPC83627 Policy definition. +------------------------------------------------------------------------------- + Rev Date Name Description + ------------------------------------------------------------------------------- + R01 < 4/22/2011> LB Update driver for Sio83627UGH support. + ------------------------------------------------------------------------------- +**/ + +#ifndef _WPC83627_POLICY_PROTOCOL_H_ +#define _WPC83627_POLICY_PROTOCOL_H_ + +EFI_FORWARD_DECLARATION (EFI_WPC83627_POLICY_PROTOCOL); + +#define EFI_WPC83627_POLICY_PROTOCOL_GUID \ + { \ + 0xd3ecc567, 0x9fd5, 0x44c1, 0x86, 0xcf, 0x5d, 0xa7, 0xa2, 0x4f, 0x4b, 0x5d \ + } + +#define EFI_WPC83627_COM1_ENABLE 0x01 +#define EFI_WPC83627_COM2_ENABLE 0x01 + +#define EFI_WPC83627_COM3_ENABLE 0x01 +#define EFI_WPC83627_COM4_ENABLE 0x01 + +#define EFI_WPC83627_LPT1_ENABLE 0x01 +#define EFI_WPC83627_LPT1_ENABLE 0x01 +#define EFI_WPC83627_FDD_ENABLE 0x01 +#define EFI_WPC83627_FDD_WRITE_ENABLE 0x01 +#define EFI_WPC83627_PS2_KBC_ENABLE 0x01 +#define EFI_WPC83627_ECIR_ENABLE 0x01 + +#define EFI_WPC83627_COM1_DISABLE 0x00 +#define EFI_WPC83627_COM2_DISABLE 0x00 + +#define EFI_WPC83627_COM3_DISABLE 0x00 +#define EFI_WPC83627_COM4_DISABLE 0x00 + +#define EFI_WPC83627_LPT1_DISABLE 0x00 +#define EFI_WPC83627_FDD_DISABLE 0x00 +#define EFI_WPC83627_FDD_WRITE_PROTECT 0x00 +#define EFI_WPC83627_PS2_KBC_DISABLE 0x00 +#define EFI_WPC83627_ECIR_DISABLE 0x00 +#define EFI_WPC83627_RESERVED_DEFAULT 0x00 + +typedef struct { + UINT16 Com1 :1; // 0 = Disable, 1 = Enable + UINT16 Lpt1 :1; // 0 = Disable, 1 = Enable + UINT16 Floppy :1; // 0 = Disable, 1 = Enable + UINT16 FloppyWriteProtect :1; // 0 = Write Protect, 1 = Write Enable + UINT16 Port80 :1; // 0 = Disable, 1 = Enable + UINT16 CIR :1; // CIR enable or disable + UINT16 Ps2Keyboard :1; // 0 = Disable, 1 = Enable + UINT16 Ps2Mouse :1; // 0 = Disable, 1 = Enable + UINT16 Com2 :1; // 0 = Disable, 1 = Enable + + UINT16 Com3 :1; // 0 = Disable, 1 = Enable + UINT16 Com4 :1; // 0 = Disable, 1 = Enable + + UINT16 Dac :1; // 0 = Disable, 1 = Enable + UINT16 Rsvd :6; +} EFI_WPC83627_DEVICE_ENABLES; + +typedef enum { + LptModeOutput, + LptModeBiDirectional, + LptModeEpp, + LptModeEcp +} EFI_LPT_MODE; + +typedef struct _EFI_WPC83627_POLICY_PROTOCOL { + EFI_WPC83627_DEVICE_ENABLES DeviceEnables; + EFI_LPT_MODE LptMode; +} EFI_WPC83627_POLICY_PROTOCOL; + +extern EFI_GUID gEfiLpcWpc83627PolicyProtocolGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/LpcWpce791Policy.h b/Vlv2TbltDevicePkg/Include/Protocol/LpcWpce791Policy.h new file mode 100644 index 0000000000..4c897da382 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/LpcWpce791Policy.h @@ -0,0 +1,60 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + LpcWpce791Policy.h + +Abstract: + + Protocol used for WPCE791 Policy definition. + +**/ + +#ifndef _WPCE791_POLICY_PROTOCOL_H_ +#define _WPCE791_POLICY_PROTOCOL_H_ + + +#define EFI_WPCE791_POLICY_PROTOCOL_GUID \ + { \ + 0xab2bee2f, 0xc1a6, 0x4399, 0x85, 0x3d, 0xc0, 0x7c, 0x77, 0x4f, 0xfd, 0xd \ + } + +#define EFI_WPCE791_PS2_KEYBOARD_ENABLE 0x01 +#define EFI_WPCE791_PS2_KEYBOARD_DISABLE 0x00 + +#define EFI_WPCE791_PS2_MOUSE_ENABLE 0x01 +#define EFI_WPCE791_PS2_MOUSE_DISABLE 0x00 + +typedef struct { + UINT16 Com1 :1; // 0 = Disable, 1 = Enable + UINT16 Lpt1 :1; // 0 = Disable, 1 = Enable + UINT16 Floppy :1; // 0 = Disable, 1 = Enable + UINT16 FloppyWriteProtect :1; // 0 = Write Protect, 1 = Write Enable + UINT16 Port80 :1; // 0 = Disable, 1 = Enable + UINT16 CIR :1; // CIR enable or disable + UINT16 Ps2Keyboard :1; // 0 = Disable, 1 = Enable + UINT16 Ps2Mouse :1; // 0 = Disable, 1 = Enable + UINT16 Com2 :1; // 0 = Disable, 1 = Enable + UINT16 Dac :1; // 0 = Disable, 1 = Enable + UINT16 Rsvd :6; +} EFI_WPCE791_DEVICE_ENABLES; + +typedef struct _EFI_WPCE791_POLICY_PROTOCOL { + EFI_WPCE791_DEVICE_ENABLES DeviceEnables; +} EFI_WPCE791_POLICY_PROTOCOL; + +extern EFI_GUID gEfiLpcWpce791PolicyProtocolGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/MmioDevice.h b/Vlv2TbltDevicePkg/Include/Protocol/MmioDevice.h new file mode 100644 index 0000000000..6848f52f06 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/MmioDevice.h @@ -0,0 +1,89 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef __MMIO_DEVICE_H__ +#define __MMIO_DEVICE_H__ + +// +// Protocol to define for the MMIO device +// +typedef struct { + // + // Address of a GUID + // + EFI_GUID *Guid; + + // + // Context for the protocol + // + VOID *Context; +} EFI_MMIO_DEVICE_PROTOCOL_ITEM; + + +typedef struct _EFI_MMIO_DEVICE_PROTOCOL EFI_MMIO_DEVICE_PROTOCOL; + +// +// The MMIO device protocol defines a memory mapped I/O device +// for use by the system. +// +struct _EFI_MMIO_DEVICE_PROTOCOL { + // + // Pointer to an ACPI_EXTENDED_HID_DEVICE_PATH structure + // containing HID/HidStr and CID/CidStr values. + // + // See the note below associated with the UnitIdentification + // field. + // + CONST ACPI_EXTENDED_HID_DEVICE_PATH *AcpiPath; + + // + // Allow the use of a shared template for the AcpiPath. + // + // If this value is non-zero UID value then the AcpiPath must + // be a template which contains only the HID/HidStr and CID/CidStr + // values. The UID/UidStr values in the AcpiPath must be zero! + // + // If this value is zero then the AcpiPath is not shared and + // must contain either a non-zero UID value or a UidStr value. + // + UINT32 UnitIdentification; + + // + // Hardware revision - ACPI _HRV value + // + UINT32 HardwareRevision; + + // + // Pointer to a data structure containing the controller + // resources and configuration. At a minimum this points + // to an EFI_PHYSICAL_ADDRESS for the base address of the + // MMIO device. + // + CONST VOID *DriverResources; + + // + // Number of protocols in the array + // + UINTN ProtocolCount; + + // + // List of protocols to define + // + CONST EFI_MMIO_DEVICE_PROTOCOL_ITEM *ProtocolArray; +}; + +extern EFI_GUID gEfiMmioDeviceProtocolGuid; + +#endif // __MMIO_DEVICE_H__ diff --git a/Vlv2TbltDevicePkg/Include/Protocol/Observable.h b/Vlv2TbltDevicePkg/Include/Protocol/Observable.h new file mode 100644 index 0000000000..31af6dd4ca --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/Observable.h @@ -0,0 +1,191 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Observable.h + +Abstract: + + Interface and GUID definitions for Observable protocol. + +**/ + +#ifndef _OBSERVABLE_PROTOCOL_H_ +#define _OBSERVABLE_PROTOCOL_H_ + +// +// GUID Definitions +// +#define OBSERVABLE_PROTOCOL_GUID \ + { \ + 0xe227c522, 0xd5fe, 0x4a53, 0x87, 0xb1, 0x0f, 0xbe, 0x57, 0x0f, 0x98, 0xe9 \ + } + +extern EFI_GUID gObservableProtocolGuid; + +typedef struct _OBS_OBSERVABLE_PROTOCOL OBS_OBSERVABLE_PROTOCOL; + +// +// Interface Definitions +// + +/** + Remove all observables. + + Remove all observable guids and all interfaces subscribed to them. + + @param VOID No Parameters. + + @return EFI_SUCCESS Successfully removed all observables and subscribed interfaces. + +**/ +typedef +EFI_STATUS +(EFIAPI *OBS_REMOVE_ALL_OBSERVABLES) ( + VOID + ); + +/** + Interface for notification functions. + + Functions that are to be used as callbacks must inherit this interface in order to be used properly. + + @param VOID* Data Parameter context to be passed to the notification function. + + @return EFI_STATUS Varies depending on implementation. + +**/ +typedef +EFI_STATUS +(EFIAPI *OBS_CALLBACK) ( + IN OUT VOID* Data + ); + +/** + Subscribe an interface with an observable guid. + + Use this to register a callback function with a guid. The function provided by CallbackInterface will be executed + whenever the appropriate observable instance specified by ReferenceGuid calls Publish. + + @param EFI_GUID ReferenceGuid The observable guid that the callback interface will subscribe to. + OBS_NOTIFY_INTERFACE CallbackInterface A pointer to the function that is subscribing to the observable. + + @return EFI_SUCCESS Successfully subscribed the interface to the observable guid. + EFI_NOT_FOUND No match could be found between the provided guid and existing observables. + EFI_OUT_OF_RESOURCES Could not subscribe to this observer due to resource limitations. + EFI_INVALID_PARAMETER Interface is already subscribed to this observer. +**/ +typedef +EFI_STATUS +(EFIAPI *OBS_SUBSCRIBE) ( + IN EFI_GUID ReferenceGuid, + IN OBS_CALLBACK CallbackInterface + ); + +/** + Unsubscribe an interface with an observable guid. + + Use this to remove an interface from the callback list associated with an observable guid. + + @param EFI_GUID ReferenceGuid The observable guid to unsubscribe the interface from. + OBS_NOTIFY_INTERFACE NotifyCallback A pointer to the interface that is being unsubscribed. + + @return EFI_SUCCESS Successfully unsubscribed the interface from the observable guid. + +**/ +typedef +EFI_STATUS +(EFIAPI *OBS_UNSUBSCRIBE) ( + IN EFI_GUID ReferenceGuid, + IN OBS_CALLBACK CallbackInterface + ); + +/** + Notify observing functions. + + Use this to notify all functions who are subscribed to the guid specified by ReferenceGuid. + + @param EFI_GUID ReferenceGuid The observable guid that contains the the list of interfaces to be notified. + VOID* Data Parameter context to be passed to the notification function. + + @return EFI_SUCCESS Successfully notified all observers listening to this guid. + EFI_NOT_FOUND No match could be found between the provided guid and existing observables. + +**/ +typedef +EFI_STATUS +(EFIAPI *OBS_PUBLISH) ( + IN EFI_GUID ReferenceGuid, + IN OUT VOID* Data + ); + +/** + Creates a new observable. + + Create a new observable that can be observed with the use of Subscribe function. + + @param EFI_GUID ReferenceGuid The observable guid to add. + + @return EFI_SUCCESS Successfully added observable. + EFI_INVALID_PARAMETER Observable already exists. + +**/ +typedef +EFI_STATUS +(EFIAPI *OBS_ADD_OBSERVABLE) ( + IN EFI_GUID ReferenceGuid + ); + +/** + Remove an observable. + + Remove an observable so that it can no longer be subscribed to. In addition, unsubscribe any functions + that are subscribed to this guid. + + @param EFI_GUID ReferenceGuid The observable guid to remove. + + @return EFI_SUCCESS Successfully removed observable. + +**/ +typedef +EFI_STATUS +(EFIAPI *OBS_REMOVE_OBSERVABLE) ( + IN EFI_GUID ReferenceGuid + ); + +// +// Protocol Definitions +// +typedef struct _OBS_LEAF { + OBS_CALLBACK Observer; + struct _OBS_LEAF* Next; +} OBS_LEAF; + +typedef struct _OBS_TREE { + EFI_GUID ObservableGuid; + OBS_LEAF* Leaf; + struct _OBS_TREE* Next; +} OBS_TREE; + +struct _OBS_OBSERVABLE_PROTOCOL { + OBS_ADD_OBSERVABLE AddObservable; + OBS_REMOVE_OBSERVABLE RemoveObservable; + OBS_SUBSCRIBE Subscribe; + OBS_UNSUBSCRIBE Unsubscribe; + OBS_PUBLISH Publish; + OBS_REMOVE_ALL_OBSERVABLES RemoveAllObservables; +} ; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/PlatformGopPolicy.h b/Vlv2TbltDevicePkg/Include/Protocol/PlatformGopPolicy.h new file mode 100644 index 0000000000..f0d021bd70 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/PlatformGopPolicy.h @@ -0,0 +1,73 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +--*/ + +/** @file +**/ + +#ifndef _PLATFORM_GOP_POLICY_PROTOCOL_H_ +#define _PLATFORM_GOP_POLICY_PROTOCOL_H_ + +#define EFI_PLATFORM_GOP_POLICY_PROTOCOL_GUID \ + { 0xec2e931b, 0x3281, 0x48a5, 0x81, 0x7, 0xdf, 0x8a, 0x8b, 0xed, 0x3c, 0x5d } + +#define EFI_BMP_IMAGE_GUID \ + { 0x878AC2CC, 0x5343, 0x46F2, 0xB5, 0x63, 0x51, 0xF8, 0x9D, 0xAF, 0x56, 0xBA } + +#define PLATFORM_GOP_POLICY_PROTOCOL_REVISION_01 0x01 +#define PLATFORM_GOP_POLICY_PROTOCOL_REVISION_02 x0222 + +#pragma pack(1) + +typedef enum { + LidClosed, + LidOpen, + LidStatusMax +} LID_STATUS; + +typedef enum { + Docked, + UnDocked, + DockStatusMax +} DOCK_STATUS; + +typedef +EFI_STATUS +(EFIAPI *GET_PLATFORM_LID_STATUS) ( + OUT LID_STATUS *CurrentLidStatus +); + +typedef +EFI_STATUS +(EFIAPI *GET_VBT_DATA) ( + OUT EFI_PHYSICAL_ADDRESS *VbtAddress, + OUT UINT32 *VbtSize +); + +#pragma pack() + +typedef struct _PLATFORM_GOP_POLICY_PROTOCOL { + UINT32 Revision; + GET_PLATFORM_LID_STATUS GetPlatformLidStatus; + GET_VBT_DATA GetVbtData; +} PLATFORM_GOP_POLICY_PROTOCOL; + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gPlatformGOPPolicyGuid; + +extern EFI_GUID gBmpImageGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/PlatformIdeInit.h b/Vlv2TbltDevicePkg/Include/Protocol/PlatformIdeInit.h new file mode 100644 index 0000000000..45add2b421 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/PlatformIdeInit.h @@ -0,0 +1,48 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PlatformIdeInit.h + +Abstract: + + EFI Platform Ide Init Protocol + +Revision History + +**/ + +#ifndef _EFI_PLATFORM_IDE_INIT_H_ +#define _EFI_PLATFORM_IDE_INIT_H_ + +// +// Global ID for the IDE Platform Protocol +// +#define EFI_PLATFORM_IDE_INIT_PROTOCOL_GUID \ + { 0x377c66a3, 0x8fe7, 0x4ee8, 0x85, 0xb8, 0xf1, 0xa2, 0x82, 0x56, 0x9e, 0x3b }; + +EFI_FORWARD_DECLARATION (EFI_PLATFORM_IDE_INIT_PROTOCOL); + + +// +// Interface structure for the Platform IDE Init Protocol +// +typedef struct _EFI_PLATFORM_IDE_INIT_PROTOCOL { + BOOLEAN SmartMode; +} EFI_PLATFORM_IDE_INIT_PROTOCOL; + +extern EFI_GUID gEfiPlatformIdeInitProtocolGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/SetupMode.h b/Vlv2TbltDevicePkg/Include/Protocol/SetupMode.h new file mode 100644 index 0000000000..87fb5237a8 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/SetupMode.h @@ -0,0 +1,84 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + SetupMode.h + +Abstract: + + EFI Setup Mode + +Revision History + +**/ + +#ifndef _EFI_SETUP_MODE_H_ +#define _EFI_SETUP_MODE_H_ + +// +// Global ID for the Setup Mode +// +#define EFI_PLATFORM_BOOT_MODE_GUID \ + { 0xce845704, 0x1683, 0x4d38, 0xa4, 0xf9, 0x7d, 0xb, 0x50, 0x77, 0x57, 0x93 } + +#define EFI_NORMAL_SETUP_GUID \ + { 0xec87d643, 0xeba4, 0x4bb5, 0xa1, 0xe5, 0x3f, 0x3e, 0x36, 0xb2, 0xd, 0xa9 } + +#define EFI_NORMAL_SETUP_RESET_NAME L"Reset" + +enum { + // + // This means: "whatever reset defaults in setup does" + // + SetupDataResetNormal = 0, + + // + // This means: "the defaults built into the BIOS" + // + SetupDataResetStandard = 1, + + // + // This means: "the manufacturing mode defaults" + // + SetupDataResetManufacturing = 2, + + // + // This means: "the oem defaults" + // + SetupDataResetOem = 3, +}; + +// +// PlatformBootMode types +// +#define PLATFORM_NORMAL_MODE 0x01 +#define PLATFORM_SAFE_MODE 0x02 +#define PLATFORM_RECOVERY_MODE 0x04 +#define PLATFORM_MANUFACTURING_MODE 0x08 +#define PLATFORM_BACK_TO_BIOS_MODE 0x10 + +extern EFI_GUID gEfiPlatformBootModeGuid; +extern EFI_GUID gEfiNormalSetupGuid; +extern CHAR16 gEfiNormalSetupName[]; +extern CHAR16 gEfiInSetupName[]; +extern CHAR16 gEfiSystemPasswordName[]; + +typedef struct { + EFI_GUID SetupGuid; + CHAR16 SetupName[0x20]; // Maximum "Setup" Name + UINT32 PlatformBootMode; +} EFI_PLATFORM_SETUP_ID; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/SmbiosSlotPopulation.h b/Vlv2TbltDevicePkg/Include/Protocol/SmbiosSlotPopulation.h new file mode 100644 index 0000000000..e677be3756 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/SmbiosSlotPopulation.h @@ -0,0 +1,52 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + SmbiosSlotPopulation.h + +Abstract: + + EFI SMBIOS slot structure control code. + +GUID: + {EF7BF7D6-F8FF-4a76-8247-C0D0D1CC49C0} + 0xef7bf7d6, 0xf8ff, 0x4a76, 0x82, 0x47, 0xc0, 0xd0, 0xd1, 0xcc, 0x49, 0xc0 + +Revision History + +**/ + +#ifndef _EFI_SMBIOS_SLOT_POPULATION_H_ +#define _EFI_SMBIOS_SLOT_POPULATION_H_ + +// +// Slot Population Protocol GUID +// +#define EFI_SMBIOS_SLOT_POPULATION_GUID \ + { 0xef7bf7d6, 0xf8ff, 0x4a76, 0x82, 0x47, 0xc0, 0xd0, 0xd1, 0xcc, 0x49, 0xc0 } + +typedef struct { + UINT16 SmbiosSlotId; // SMBIOS Slot ID + BOOLEAN InUse; // Does the slot have a card in it + BOOLEAN Disabled; // Should the slot information be in SMBIOS +} EFI_SMBIOS_SLOT_ENTRY; + +typedef struct { + UINT32 NumberOfEntries; + EFI_SMBIOS_SLOT_ENTRY *SlotEntries; +} EFI_SMBIOS_SLOT_POPULATION_INFO; + +extern EFI_GUID gEfiSmbiosSlotPopulationGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/Speaker.h b/Vlv2TbltDevicePkg/Include/Protocol/Speaker.h new file mode 100644 index 0000000000..f76d63286f --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/Speaker.h @@ -0,0 +1,70 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + Speaker.h + +Abstract: + + EFI Speaker Interface Protocol + +Revision History + +**/ + +#ifndef _EFI_SPEAKER_H +#define _EFI_SPEAKER_H + +// +// Global Id for Speaker Interface +// +#define EFI_SPEAKER_INTERFACE_PROTOCOL_GUID \ + { \ + 0x400b4476, 0x3081, 0x11d6, 0x87, 0xed, 0x00, 0x06, 0x29, 0x45, 0xc3, 0xb9 \ + } + +typedef struct _EFI_SPEAKER_IF_PROTOCOL EFI_SPEAKER_IF_PROTOCOL; + +// +// Beep Code +// +typedef +EFI_STATUS +(EFIAPI *EFI_GENERATE_BEEP) ( + IN EFI_SPEAKER_IF_PROTOCOL * This, + IN UINTN NumberOfBeep, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ); + +// +// Set Frequency +// +typedef +EFI_STATUS +(EFIAPI *EFI_SPEAKER_SET_FREQUENCY) ( + IN EFI_SPEAKER_IF_PROTOCOL * This, + IN UINT16 Frequency + ); + +// +// Protocol definition +// +struct _EFI_SPEAKER_IF_PROTOCOL { + EFI_SPEAKER_SET_FREQUENCY SetSpeakerToneFrequency; + EFI_GENERATE_BEEP GenerateBeep; +} ; + +extern EFI_GUID gEfiSpeakerInterfaceProtocolGuid; +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/TcoReset.h b/Vlv2TbltDevicePkg/Include/Protocol/TcoReset.h new file mode 100644 index 0000000000..d8047d408b --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/TcoReset.h @@ -0,0 +1,72 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + TcoReset.h + +Abstract: + + Protocol to communicate with ICH TCO. + +GUID Info: + {A6A79162-E325-4c30-BCC3-59373064EFB3} + 0xa6a79162, 0xe325, 0x4c30, 0xbc, 0xc3, 0x59, 0x37, 0x30, 0x64, 0xef, 0xb3); + + +--*/ + +#ifndef _TCO_RESET_H_ +#define _TCO_RESET_H_ + + +#define EFI_TCO_RESET_PROTOCOL_GUID \ + {0xa6a79162, 0xe325, 0x4c30, 0xbc, 0xc3, 0x59, 0x37, 0x30, 0x64, 0xef, 0xb3} + +typedef struct _EFI_TCO_RESET_PROTOCOL EFI_TCO_RESET_PROTOCOL; + +/** + Enables the TCO timer to reset the system in case of a system hang. This is + used when writing the clock registers. + + @param[in] RcrbGcsSaveValue This is the value of the RCRB GCS register before it is + changed by this procedure. This will be used to restore + the settings of this register in PpiDisableTcoReset. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCO_RESET_PROTOCOL_ENABLE_TCO_RESET) ( + IN UINT32 *RcrbGcsSaveValue + ); + +/** + Disables the TCO timer. This is used after writing the clock registers. + + @param[in] RcrbGcsRestoreValue Value saved in PpiEnableTcoReset so that it can + restored. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCO_RESET_PROTOCOL_DISABLE_TCO_RESET) ( + OUT UINT32 RcrbGcsRestoreValue + ); + +typedef struct _EFI_TCO_RESET_PROTOCOL { + EFI_TCO_RESET_PROTOCOL_ENABLE_TCO_RESET EnableTcoReset; + EFI_TCO_RESET_PROTOCOL_DISABLE_TCO_RESET DisableTcoReset; +} EFI_TCO_RESET_PROTOCOL; + +extern EFI_GUID gEfiTcoResetProtocolGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/TpmMp.h b/Vlv2TbltDevicePkg/Include/Protocol/TpmMp.h new file mode 100644 index 0000000000..8ce084867d --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/TpmMp.h @@ -0,0 +1,141 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Tpm.h + +Abstract: + + +--*/ + +#ifndef __EFI_TPM_MP_DRIVER_PROTOCOL_H__ +#define __EFI_TPM_MP_DRIVER_PROTOCOL_H__ + + +#define EFI_TPM_MP_DRIVER_PROTOCOL_GUID \ + { 0xde161cfe, 0x1e60, 0x42a1, 0x8c, 0xc3, 0xee, 0x7e, 0xf0, 0x73, 0x52, 0x12 } + + +EFI_FORWARD_DECLARATION (EFI_TPM_MP_DRIVER_PROTOCOL); + +#define TPM_DRIVER_STATUS 0 +#define TPM_DEVICE_STATUS 1 + +#define TPM_DRIVER_OK 0 +#define TPM_DRIVER_FAILED 1 +#define TPM_DRIVER_NOT_OPENED 2 +#define TPM_DEVICE_OK 0 +#define TPM_DEVICE_UNRECOVERABLE 1 +#define TPM_DEVICE_RECOVERABLE 2 +#define TPM_DEVICE_NOT_FOUND 3 + +// +// Prototypes for the TPM MP Driver Protocol +// + +/** + This service Open the TPM interface + + @param[in] This A pointer to the EFI_TPM_MP_DRIVER_PROTOCOL. + + @retval EFI_SUCCESS Operation completed successfully + @retval EFI_DEVICE_ERROR The command was unsuccessful + @retval EFI_NOT_FOUND The component was not running + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TPM_MP_INIT) ( + IN EFI_TPM_MP_DRIVER_PROTOCOL *This + ); + +/** + This service close the TPM interface and deactivate TPM + + @param[in] This A pointer to the EFI_TPM_MP_DRIVER_PROTOCOL. + + @retval EFI_SUCCESS Operation completed successfully + @retval EFI_DEVICE_ERROR The command was unsuccessful + @retval EFI_NOT_FOUND The component was not running + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TPM_MP_CLOSE) ( + IN EFI_TPM_MP_DRIVER_PROTOCOL *This + ); + +/** + This service get the current status infomation of TPM + + @param[in] This A pointer to the EFI_TPM_MP_DRIVER_PROTOCOL. + @param[in] ReqStatusType Requested type of status information, driver or device. + @param[in] Status Pointer to the returned status. + + @retval EFI_SUCCESS Operation completed successfully + @retval EFI_DEVICE_ERROR The command was unsuccessful + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect + @retval EFI_BUFFER_TOO_SMALL The receive buffer is too small + @retval EFI_NOT_FOUND The component was not running + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TPM_MP_GET_STATUS_INFO) ( + IN EFI_TPM_MP_DRIVER_PROTOCOL *This, + IN UINT32 ReqStatusType, + OUT UINT32 *Status + ); + +/** + This service transmit data to the TPM and get response from TPM + + @param[in] This A pointer to the EFI_TPM_MP_DRIVER_PROTOCOL. + @param[in] TransmitBuf Pointer to a buffer containing TPM transmit data. + @param[in] TransmitBufLen Sizeof TPM input buffer in bytes. + @param[in] ReceiveBuf Pointer to a buffer containing TPM receive data. + @param[in] ReceiveBufLen On input, size of TPM receive buffer in bytes. + On output, number of bytes written. + + @retval EFI_SUCCESS Operation completed successfully + @retval EFI_DEVICE_ERROR The command was unsuccessful + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect + @retval EFI_BUFFER_TOO_SMALL The receive buffer is too small + @retval EFI_NOT_FOUND The component was not running + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TPM_MP_TRANSMIT) ( + IN EFI_TPM_MP_DRIVER_PROTOCOL *This, + IN UINT8 *TransmitBuffer, + IN UINT32 TransmitBufferLen, + OUT UINT8 *ReceiveBuf, + IN OUT UINT32 *ReceiveBufLen + ); + + + +typedef struct _EFI_TPM_MP_DRIVER_PROTOCOL { + EFI_TPM_MP_INIT Init; + EFI_TPM_MP_CLOSE Close; + EFI_TPM_MP_GET_STATUS_INFO GetStatusInfo; + EFI_TPM_MP_TRANSMIT Transmit; +} EFI_TPM_MP_DRIVER_PROTOCOL; + +extern EFI_GUID gEfiTpmMpDriverProtocolGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/UsbPolicy.h b/Vlv2TbltDevicePkg/Include/Protocol/UsbPolicy.h new file mode 100644 index 0000000000..31ac22ea50 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/UsbPolicy.h @@ -0,0 +1,131 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + UsbPolicy.h + +Abstract: + +--*/ + +#ifndef _USB_POLICY_H_ +#define _USB_POLICY_H_ + +EFI_FORWARD_DECLARATION (EFI_USB_POLICY_PROTOCOL); + +#define USB_POLICY_GUID \ + {\ + 0xf617b358, 0x12cf, 0x414a, 0xa0, 0x69, 0x60, 0x67, 0x7b, 0xda, 0x13, 0xb4\ + } + +#define TIANO_CODE_BASE 0x00 +#define ICBD_CODE_BASE 0x01 + +#define ATUO_TYPE 0x00 +#define USB_FDD_TYPE 0x01 +#define HDD_TYPE 0x02 +#define ZIP_TYPE 0x03 +#define CDROM_TYPE 0x04 +#define SIZE_TYPE 0x05 + +#define ZIP_FDD 0x80 + +#define FDD_EMULATION 0x00 +#define HDD_EMULATION 0x01 + +#define HIGH_SPEED 0x00 +#define FULL_SPEED 0x01 +#define SUPER_SPEED 0x02 + +#define LEGACY_KB_EN 0x01 +#define LEGACY_KB_DIS 0x00 +#define LEGACY_MS_EN 0x01 +#define LEGACY_MS_DIS 0x00 +#define LEGACY_USB_EN 0x00 +#define LEGACY_USB_DIS 0x01 +#define LEGACY_FREE_SUPP 0x01 +#define LEGACY_FREE_UN_SUPP 0x00 +#define LEGACY_PERIOD_SUPP 0x01 +#define LEGACY_PERIOD_UN_SUPP 0x00 + +#define LEGACY_USB_TIME_TUE_ENABLE 0x01 +#define LEGACY_USB_TIME_TUE_DISABLE 0x00 +#define USB_HAVE_HUB_INTERNEL 0x01 +#define USB_NOT_HAVE_HUB_INTERNEL 0x00 + +#define USB_POLICY_PROTOCOL_REVISION_1 1 +#define USB_POLICY_PROTOCOL_REVISION_2 2 + +#ifndef __GNUC__ +#pragma warning ( disable : 4306 ) +#pragma warning ( disable : 4054 ) +#endif + +#define GET_USB_CFG (UsbCfg);\ + do{\ + UINT16 *pSegOfEbda;\ + UINT32 mToEbda;\ + pSegOfEbda = (UINT16 *)(UINTN)0x40E;\ + mToEbda = (UINT32)(((UINTN)(*pSegOfEbda) << 4) + 0x80);\ + UsbCfg = (USB_CFG *)(UINTN)mToEbda;\ + }while(0); + +#pragma pack(1) +typedef struct { + UINT8 HasUSBKeyboard:1; + UINT8 HasUSBMouse:1; + UINT8 LegacyFreeSupport:1; + UINT8 UsbOperationMode:1; + UINT8 LegacyKBEnable:1; + UINT8 LegacyMSEnable:1; + UINT8 USBPeriodSupport:1; + UINT8 Reserved:1; +} USB_DEVICE_INFOR; + +typedef struct { + UINT8 Codebase; + UINT8 USBHDDForceType; + UINT8 Configurated; + UINT8 LpcAcpiBase; + UINT8 AcpiTimerReg; + UINT8 Reserved1[0x01]; + UINT8 LegacyUsbEnable; + USB_DEVICE_INFOR UsbDeviceInfor; + UINT16 UsbEmulationSize; + UINT8 Reserved2[0x06]; +} USB_CFG; +#pragma pack() + +typedef struct _EFI_USB_POLICY_PROTOCOL{ + UINT8 Version; + UINT8 UsbMassStorageEmulationType; // 1: FDD_Type; 2: HDD_Type; other:Auto_Type* + UINT8 UsbOperationMode; // 0: High_Speed; 1: Full_Speed; + UINT8 LegacyKBEnable; // 0: Disabled; 1: Enabled* + UINT8 LegacyMSEnable; // 0: Disabled; 1: Enabled* + UINT8 USBPeriodSupport; // 0; Unsupport; 1: Support + UINT8 LegacyUsbEnable; // 1: Disabled; 0: Enabled* + UINT8 LegacyFreeSupport; // 0: Unsupport; 1: Support + UINT8 CodeBase; + UINT8 LpcAcpiBase; // 40h(default) + UINT8 AcpiTimerReg; + UINT8 UsbTimeTue; + UINT8 InternelHubExist; // 1: Host have internel hub on board; 0: No internel hub on board + UINT8 EnumWaitPortStableStall; // Value for wait port stable when enum a new dev. + UINT16 UsbEmulationSize; // Mbytes. + UINT8 UsbZipEmulationType; + UINT8 Reserved[3]; // Reserved fields for future expansion w/o protocol change +} EFI_USB_POLICY_PROTOCOL; + +extern EFI_GUID gUsbPolicyGuid; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/Protocol/VlvPlatformPolicy.h b/Vlv2TbltDevicePkg/Include/Protocol/VlvPlatformPolicy.h new file mode 100644 index 0000000000..8e500935d0 --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/Protocol/VlvPlatformPolicy.h @@ -0,0 +1,108 @@ +/** + Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + VlvPlatformPolicy.h + +Abstract: + + Interface definition details between MCH and platform drivers during DXE phase. + +--*/ + +#ifndef _VLV_PLATFORM_POLICY_H_ +#define _VLV_PLATFORM_POLICY_H_ + +// +// VLV Policy provided by platform for DXE phase {5BAB88BA-E0E2-4674-B6AD-B812F6881CD6} +// +#define DXE_VLV_PLATFORM_POLICY_GUID \ + {0x5bab88ba, 0xe0e2, 0x4674, 0xb6, 0xad, 0xb8, 0x12, 0xf6, 0x88, 0x1c, 0xd6} + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gDxeVlvPlatformPolicyGuid; + +// +// Protocol revision number +// Any backwards compatible changes to this protocol will result in an update in the revision number +// Major changes will require publication of a new protocol +// +#define DXE_VLV_PLATFORM_POLICY_PROTOCOL_REVISION 0 + + +typedef struct { + UINT8 PFITStatus; + UINT8 IgdTheramlSupport; + UINT8 ALSEnabled; + UINT8 LidStatus; +} IGD_PANEL_FEATURES; + +typedef struct { + UINT8 Reserved00; + UINT8 Reserved01; + UINT16 Reserved02; + UINT16 Reserved03; + UINT16 Reserved04; + UINT16 Reserved05; + UINT16 Reserved06; + UINT16 Reserved07; + UINT16 Reserved08; + UINT16 Reserved09; + UINT16 Reserved0A; + UINT16 Reserved0B; + UINT16 Reserved0C; + UINT16 Reserved0D; + UINT8 Reserved0E; + UINT8 Reserved0F; + UINT32 Reserved10; + UINT32 Reserved11; + UINT32 Reserved12; + UINT32 Reserved13; + UINT32 Reserved14; + UINT8 Reserved15; + UINT8 Reserved16; +} DPTF_SETTINGS; + +// +// MCH DXE Platform Policiy ================================================== +// + +#define NO_AUDIO 0 +#define HD_AUDIO 1 +#define LPE_AUDIO 2 + +typedef struct _DXE_VLV_PLATFORM_POLICY_PROTOCOL { + UINT8 Revision; + IGD_PANEL_FEATURES IgdPanelFeatures; + DPTF_SETTINGS Reserved; + UINT8 GraphicReserve00; + UINT8 GraphicsPerfAnalyzers; + UINT8 PwmReserved00; + UINT8 PwmReserved01; + UINT8 PmSupport; + UINT8 GraphicReserve01; + UINT8 GfxPause; + UINT8 GraphicsFreqReq; + UINT8 GraphicReserve03; + UINT8 GraphicReserve02; + UINT8 GraphicReserve04; + UINT8 PavpMode; + UINT8 GraphicReserve05; + UINT8 UlClockGating; + UINT8 IdleReserve; + UINT8 AudioTypeSupport; + UINT8 GraphicReserve06; +} DXE_VLV_PLATFORM_POLICY_PROTOCOL; + +#endif diff --git a/Vlv2TbltDevicePkg/Include/SetupMode.h b/Vlv2TbltDevicePkg/Include/SetupMode.h new file mode 100644 index 0000000000..f0ec67c08e --- /dev/null +++ b/Vlv2TbltDevicePkg/Include/SetupMode.h @@ -0,0 +1,90 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + SetupMode.h + +Abstract: + + EFI Setup Mode + + + +--*/ + +#ifndef _EFI_SETUP_MODE_H_ +#define _EFI_SETUP_MODE_H_ + +// +// Global ID for the Setup Mode +// +#define EFI_PLATFORM_BOOT_MODE_GUID \ + { 0xce845704, 0x1683, 0x4d38, 0xa4, 0xf9, 0x7d, 0xb, 0x50, 0x77, 0x57, 0x93 } + +#define EFI_NORMAL_SETUP_GUID \ + { 0xec87d643, 0xeba4, 0x4bb5, 0xa1, 0xe5, 0x3f, 0x3e, 0x36, 0xb2, 0xd, 0xa9 } + +#define EFI_NORMAL_SETUP_RESET_NAME L"Reset" + +enum { + // + // This means: "whatever reset defaults in setup does" + // + SetupDataResetNormal = 0, + + // + // This means: "the defaults built into the BIOS" + // + SetupDataResetStandard = 1, + + // + // This means: "the manufacturing mode defaults" + // + SetupDataResetManufacturing = 2, + + // + // This means: "the oem defaults" + // + SetupDataResetOem = 3, +}; + +// +// PlatformBootMode types +// +#define PLATFORM_NORMAL_MODE 0x01 +#define PLATFORM_SAFE_MODE 0x02 +#define PLATFORM_RECOVERY_MODE 0x04 +#define PLATFORM_MANUFACTURING_MODE 0x08 +#define PLATFORM_BACK_TO_BIOS_MODE 0x10 + +extern EFI_GUID gEfiPlatformBootModeGuid; + +#define NORMAL_SETUP_NAME L"Setup" +#define IN_SETUP_NAME L"InSetup" +#define SYSTEM_PASSWORD_NAME L"SystemPassword" +#define BOOT_TIME_NAME L"BootTime" + +extern EFI_GUID gEfiNormalSetupGuid; +extern CHAR16 gEfiNormalSetupName[]; +extern CHAR16 gEfiInSetupName[]; +extern CHAR16 gEfiSystemPasswordName[]; + +typedef struct { + EFI_GUID SetupGuid; + CHAR16 SetupName[0x20]; // Maximum "Setup" Name + UINT32 PlatformBootMode; +} EFI_PLATFORM_SETUP_ID; + +#endif diff --git a/Vlv2TbltDevicePkg/IntelGopDepex/IntelGopDriver.depex b/Vlv2TbltDevicePkg/IntelGopDepex/IntelGopDriver.depex new file mode 100644 index 0000000000..011f929f0a --- /dev/null +++ b/Vlv2TbltDevicePkg/IntelGopDepex/IntelGopDriver.depex @@ -0,0 +1 @@ +“.ì2¥Hߊ‹í<] \ No newline at end of file diff --git a/Vlv2TbltDevicePkg/Library/BiosIdLib/BiosIdLib.c b/Vlv2TbltDevicePkg/Library/BiosIdLib/BiosIdLib.c new file mode 100644 index 0000000000..01897b347c --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/BiosIdLib/BiosIdLib.c @@ -0,0 +1,342 @@ +/*++ + +Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + BiosIdLib.c + +Abstract: + + Boot service DXE BIOS ID library implementation. + + These functions in this file can be called during DXE and cannot be called during runtime + or in SMM which should use a RT or SMM library. + +--*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +EFI_STATUS +GetImageFromFv ( + IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv, + IN EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + OUT VOID **Buffer, + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 AuthenticationStatus; + + // + // Read desired section content in NameGuid file + // + *Buffer = NULL; + *Size = 0; + Status = Fv->ReadSection ( + Fv, + NameGuid, + SectionType, + 0, + Buffer, + Size, + &AuthenticationStatus + ); + + if (EFI_ERROR (Status) && (SectionType == EFI_SECTION_TE)) { + // + // Try reading PE32 section, since the TE section does not exist + // + *Buffer = NULL; + *Size = 0; + Status = Fv->ReadSection ( + Fv, + NameGuid, + EFI_SECTION_PE32, + 0, + Buffer, + Size, + &AuthenticationStatus + ); + } + + if (EFI_ERROR (Status) && + ((SectionType == EFI_SECTION_TE) || (SectionType == EFI_SECTION_PE32))) { + // + // Try reading raw file, since the desired section does not exist + // + *Buffer = NULL; + *Size = 0; + Status = Fv->ReadFile ( + Fv, + NameGuid, + Buffer, + Size, + &FileType, + &Attributes, + &AuthenticationStatus + ); + } + + return Status; +} + + +EFI_STATUS +GetImageEx ( + IN EFI_HANDLE ImageHandle, + IN EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + OUT VOID **Buffer, + OUT UINTN *Size, + BOOLEAN WithinImageFv + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + + EFI_FIRMWARE_VOLUME2_PROTOCOL *ImageFv; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + + + if (ImageHandle == NULL && WithinImageFv) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_NOT_FOUND; + ImageFv = NULL; + if (ImageHandle != NULL) { + Status = gBS->HandleProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + if (EFI_ERROR (Status)) { + return Status; + } + Status = gBS->HandleProtocol ( + LoadedImage->DeviceHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &ImageFv + ); + if (!EFI_ERROR (Status)) { + Status = GetImageFromFv (ImageFv, NameGuid, SectionType, Buffer, Size); + } + } + + if (Status == EFI_SUCCESS || WithinImageFv) { + return Status; + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Find desired image in all Fvs + // + for (Index = 0; Index < HandleCount; ++Index) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID**)&Fv + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool(HandleBuffer); + return Status; + } + + if (ImageFv != NULL && Fv == ImageFv) { + continue; + } + + Status = GetImageFromFv (Fv, NameGuid, SectionType, Buffer, Size); + + if (!EFI_ERROR (Status)) { + break; + } + } + gBS->FreePool(HandleBuffer); + + // + // Not found image + // + if (Index == HandleCount) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + This function returns BIOS ID by searching HOB or FV. + + @param BiosIdImage The BIOS ID got from HOB or FV. + + @retval EFI_SUCCESS All parameters were valid and BIOS ID has been got. + @retval EFI_NOT_FOUND BiosId image is not found, and no parameter will be modified. + @retval EFI_INVALID_PARAMETER The parameter is NULL. + +**/ +EFI_STATUS +GetBiosId ( + OUT BIOS_ID_IMAGE *BiosIdImage + ) + +{ + EFI_STATUS Status; + VOID *Address = NULL; + UINTN Size = 0; + + DEBUG ((EFI_D_INFO, "Get BIOS ID from FV\n")); + + Status = GetImageEx ( + NULL, + &gEfiBiosIdGuid, + EFI_SECTION_RAW, + &Address, + &Size, + FALSE + ); + + if (Status == EFI_SUCCESS) { + // + // BiosId image is present in FV + // + if (Address != NULL) { + Size = sizeof (BIOS_ID_IMAGE); + gBS->CopyMem ( + (void *) BiosIdImage, + Address, + Size + ); + // + // GetImage () allocated buffer for Address, now clear it. + // + gBS->FreePool (Address); + + DEBUG ((EFI_D_INFO, "Get BIOS ID from FV successfully\n")); + DEBUG ((EFI_D_INFO, "BIOS ID: %s\n", (CHAR16 *) (&(BiosIdImage->BiosIdString)))); + + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + +/** + This function returns the Version & Release Date and Time by getting and converting + BIOS ID. + + @param BiosVersion The Bios Version out of the conversion. + @param BiosReleaseDate The Bios Release Date out of the conversion. + @param BiosReleaseTime - The Bios Release Time out of the conversion. + + @retval EFI_SUCCESS - BIOS Version & Release Date and Time have been got successfully. + @retval EFI_NOT_FOUND - BiosId image is not found, and no parameter will be modified. + @retval EFI_INVALID_PARAMETER - All the parameters are NULL. + +**/ +EFI_STATUS +GetBiosVersionDateTime ( + OUT CHAR16 *BiosVersion, OPTIONAL + OUT CHAR16 *BiosReleaseDate, OPTIONAL + OUT CHAR16 *BiosReleaseTime OPTIONAL + ) +{ + EFI_STATUS Status; + BIOS_ID_IMAGE BiosIdImage; + + if ((BiosVersion == NULL) && (BiosReleaseDate == NULL) && (BiosReleaseTime == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = GetBiosId (&BiosIdImage); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + if (BiosVersion != NULL) { + // + // Fill the BiosVersion data from the BIOS ID. + // + StrCpy (BiosVersion, (CHAR16 *) (&(BiosIdImage.BiosIdString))); + } + + if (BiosReleaseDate != NULL) { + // + // Fill the build timestamp date from the BIOS ID in the "MM/DD/YY" format. + // + BiosReleaseDate[0] = BiosIdImage.BiosIdString.TimeStamp[2]; + BiosReleaseDate[1] = BiosIdImage.BiosIdString.TimeStamp[3]; + BiosReleaseDate[2] = (CHAR16) ((UINT8) ('/')); + + BiosReleaseDate[3] = BiosIdImage.BiosIdString.TimeStamp[4]; + BiosReleaseDate[4] = BiosIdImage.BiosIdString.TimeStamp[5]; + BiosReleaseDate[5] = (CHAR16) ((UINT8) ('/')); + + // + // Add 20 for SMBIOS table + // Current Linux kernel will misjudge 09 as year 0, so using 2009 for SMBIOS table + // + BiosReleaseDate[6] = '2'; + BiosReleaseDate[7] = '0'; + BiosReleaseDate[8] = BiosIdImage.BiosIdString.TimeStamp[0]; + BiosReleaseDate[9] = BiosIdImage.BiosIdString.TimeStamp[1]; + + BiosReleaseDate[10] = (CHAR16) ((UINT8) ('\0')); + } + + if (BiosReleaseTime != NULL) { + + // + // Fill the build timestamp time from the BIOS ID in the "HH:MM" format. + // + + BiosReleaseTime[0] = BiosIdImage.BiosIdString.TimeStamp[6]; + BiosReleaseTime[1] = BiosIdImage.BiosIdString.TimeStamp[7]; + BiosReleaseTime[2] = (CHAR16) ((UINT8) (':')); + + BiosReleaseTime[3] = BiosIdImage.BiosIdString.TimeStamp[8]; + BiosReleaseTime[4] = BiosIdImage.BiosIdString.TimeStamp[9]; + + BiosReleaseTime[5] = (CHAR16) ((UINT8) ('\0')); + } + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/Library/BiosIdLib/BiosIdLib.inf b/Vlv2TbltDevicePkg/Library/BiosIdLib/BiosIdLib.inf new file mode 100644 index 0000000000..59058febac --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/BiosIdLib/BiosIdLib.inf @@ -0,0 +1,55 @@ +#/*++ +# +# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +# +# Module Name: +# +# BiosIdLib.inf +# +# Abstract: +# +# Component description file for BIOS ID library +# +#--*/ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BiosIdLib + FILE_GUID = 98546145-64F1-4d2e-814F-6BF963DB7930 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BiosIdLib + PI_SPECIFICATION_VERSION = 0x0001000A + +[Sources] + BiosIdLib.c + +[Packages] + MdePkg/MdePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + +[LibraryClasses] + HobLib + +[Guids] + gEfiBiosIdGuid + +[Protocols] + gEfiLoadedImageProtocolGuid + gEfiFirmwareVolume2ProtocolGuid + +[Depex] + gEfiLoadedImageProtocolGuid AND + gEfiFirmwareVolume2ProtocolGuid diff --git a/Vlv2TbltDevicePkg/Library/CpuIA32Lib/CpuIA32Lib.inf b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/CpuIA32Lib.inf new file mode 100644 index 0000000000..11dff9ff68 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/CpuIA32Lib.inf @@ -0,0 +1,46 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# Module Name: +# +# CpuIA32Lib.inf +# +# Abstract: +# +# Component description file for the Cpu IA32 library. +# +#--*/ + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = CpuIA32Lib + FILE_GUID = 98546178-64F1-4d2e-814F-6BF963DB7930 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CpuIA32Lib + PI_SPECIFICATION_VERSION = 0x0001000A + +[Sources] + EfiCpuVersion.c + +[Sources.IA32] + IA32/CpuIA32.c + +[Sources.X64] + X64/Cpu.asm + X64/Cpu.S + +[Packages] + MdePkg/MdePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec diff --git a/Vlv2TbltDevicePkg/Library/CpuIA32Lib/EfiCpuVersion.c b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/EfiCpuVersion.c new file mode 100644 index 0000000000..4d3f1e6982 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/EfiCpuVersion.c @@ -0,0 +1,75 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + EfiCpuVersion.c + +Abstract: + + Provide cpu version extract considering extended family & model ID. +--*/ + +#include + +/** + Extract CPU detail version infomation + + @param FamilyId FamilyId, including ExtendedFamilyId + @param Model Model, including ExtendedModel + @param SteppingId SteppingId + @param Processor Processor + +**/ +VOID +EFIAPI +EfiCpuVersion ( + IN OUT UINT16 *FamilyId, OPTIONAL + IN OUT UINT8 *Model, OPTIONAL + IN OUT UINT8 *SteppingId, OPTIONAL + IN OUT UINT8 *Processor OPTIONAL + ) + +{ + EFI_CPUID_REGISTER Register; + UINT8 TempFamilyId; + + EfiCpuid (EFI_CPUID_VERSION_INFO, &Register); + + if (SteppingId != NULL) { + *SteppingId = (UINT8) (Register.RegEax & 0xF); + } + + if (Processor != NULL) { + *Processor = (UINT8) ((Register.RegEax >> 12) & 0x3); + } + + if (Model != NULL || FamilyId != NULL) { + TempFamilyId = (UINT8) ((Register.RegEax >> 8) & 0xF); + + if (Model != NULL) { + *Model = (UINT8) ((Register.RegEax >> 4) & 0xF); + if (TempFamilyId == 0x6 || TempFamilyId == 0xF) { + *Model = (UINT8) (*Model | ((Register.RegEax >> 12) & 0xF0)); + } + } + + if (FamilyId != NULL) { + *FamilyId = TempFamilyId; + if (TempFamilyId == 0xF) { + *FamilyId = (UINT8 ) (*FamilyId + (UINT16) ((Register.RegEax >> 20) & 0xFF)); + } + } + } +} diff --git a/Vlv2TbltDevicePkg/Library/CpuIA32Lib/IA32/CpuIA32.S b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/IA32/CpuIA32.S new file mode 100644 index 0000000000..b0c5b2898d --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/IA32/CpuIA32.S @@ -0,0 +1,228 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +#Module Name: +# +# CpuIA32.c +# +#Abstract: +# +#--*/ + +##include "CpuIA32.h" +#include "EfiBind.h" + +#--------------------------------------------------------------------------- + .586p: + #.MODEL flat,C + .code: + +#--------------------------------------------------------------------------- + +.globl ASM_PFX(EfiHalt) +.globl ASM_PFX(EfiWbinvd) +.globl ASM_PFX(EfiInvd) +.globl ASM_PFX(EfiCpuid) +.globl ASM_PFX(EfiReadMsr) +.globl ASM_PFX(EfiWriteMsr) +.globl ASM_PFX(EfiReadTsc) +.globl ASM_PFX(EfiDisableCache) +.globl ASM_PFX(EfiEnableCache) +.globl ASM_PFX(EfiGetEflags) +.globl ASM_PFX(EfiDisableInterrupts) +.globl ASM_PFX(EfiEnableInterrupts) +.globl ASM_PFX(EfiCpuidExt) + + +#VOID +#EfiHalt ( +# VOID +#) +ASM_PFX(EfiHalt): + hlt + ret +#EfiHalt ENDP + +#VOID +#EfiWbinvd ( +# VOID +#) +ASM_PFX(EfiWbinvd): + wbinvd + ret +#EfiWbinvd ENDP + +#VOID +#EfiInvd ( +# VOID +#) +ASM_PFX(EfiInvd): + invd + ret +#EfiInvd ENDP + +#VOID +#EfiCpuid (IN UINT32 RegisterInEax, +# OUT EFI_CPUID_REGISTER *Reg OPTIONAL) +ASM_PFX(EfiCpuid): + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %esi + pushl %edi + pushal + + movl 8(%ebp), %eax #RegisterInEax + cpuid + cmpl $0, 0xC(%ebp) # Reg + je L1 + movl 0xC(%ebp), %edi # Reg + + movl %eax, (%edi) # Reg->RegEax + movl %ebx, 4(%edi) # Reg->RegEbx + movl %ecx, 8(%edi) # Reg->RegEcx + movl %edx, 0xC(%edi) # Reg->RegEdx + +L1: + popal + popl %edi + popl %esi + popl %ebx + popl %ebp + + ret +#EfiCpuid ENDP + + +#UINT64 +#EfiReadMsr ( +# IN UINT32 Index +# ); +ASM_PFX(EfiReadMsr): + movl 4(%esp), %ecx # Index + rdmsr + ret +#EfiReadMsr ENDP + +#VOID +#EfiWriteMsr ( +# IN UINT32 Index, +# IN UINT64 Value +# ); +ASM_PFX(EfiWriteMsr): + movl 4(%esp), %ecx # Index + movl 8(%esp), %eax # DWORD PTR Value[0] + movl 0xC(%esp), %edx # DWORD PTR Value[4] + wrmsr + ret +#EfiWriteMsr ENDP + +#UINT64 +#EfiReadTsc ( +# VOID +# ) +ASM_PFX(EfiReadTsc): + rdtsc + ret +#EfiReadTsc ENDP + +#VOID +#EfiDisableCache ( +# VOID +#) +ASM_PFX(EfiDisableCache): + movl %cr0, %eax + bswapl %eax + andb $0x60, %al + cmpb $0x60, %al + je L2 + movl %cr0, %eax + orl $0x60000000, %eax + movl %eax, %cr0 + wbinvd +L2: + ret +#EfiDisableCache ENDP + +#VOID +#EfiEnableCache ( +# VOID +# ) +ASM_PFX(EfiEnableCache): + wbinvd + movl %cr0, %eax + andl $0x9fffffff, %eax + movl %eax, %cr0 + ret +#EfiEnableCache ENDP + +#UINT32 +#EfiGetEflags ( +# VOID +# ) +ASM_PFX(EfiGetEflags): + pushfl + popl %eax + ret +#EfiGetEflags ENDP + +#VOID +#EfiDisableInterrupts ( +# VOID +# ) +ASM_PFX(EfiDisableInterrupts): + cli + ret +#EfiDisableInterrupts ENDP + +#VOID +#EfiEnableInterrupts ( +# VOID +# ) +ASM_PFX(EfiEnableInterrupts): + sti + ret +#EfiEnableInterrupts ENDP + +#VOID +#EfiCpuidExt ( +# IN UINT32 RegisterInEax, +# IN UINT32 CacheLevel, +# OUT EFI_CPUID_REGISTER *Regs +# ) +ASM_PFX(EfiCpuidExt): + push %ebx + push %edi + push %esi + pushal + + movl 0x30(%esp), %eax # RegisterInEax + movl 0x34(%esp), %ecx # CacheLevel + cpuid + movl 0x38(%esp), %edi # DWORD PTR Regs + + movl %eax, (%edi) # Reg->RegEax + movl %ebx, 4(%edi) # Reg->RegEbx + movl %ecx, 8(%edi) # Reg->RegEcx + movl %edx, 0xC(%edi) # Reg->RegEdx + + popal + pop %esi + pop %edi + pop %ebx + ret +#EfiCpuidExt ENDP + + + diff --git a/Vlv2TbltDevicePkg/Library/CpuIA32Lib/IA32/CpuIA32.asm b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/IA32/CpuIA32.asm new file mode 100644 index 0000000000..2abef79be1 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/IA32/CpuIA32.asm @@ -0,0 +1,211 @@ +; +; This file contains an 'Intel Sample Driver' and is +; licensed for Intel CPUs and chipsets under the terms of your +; license agreement with Intel or your vendor. This file may +; be modified by the user, subject to additional terms of the +; license agreement +; +; +; Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; + +;Module Name: +; +; CpuIA32.c +; +;Abstract: +; +;--*/ + +;#include "CpuIA32.h" + +;--------------------------------------------------------------------------- + .586p + .model flat,C + .code + +;--------------------------------------------------------------------------- +;VOID +;EfiHalt ( +; VOID +;) +EfiHalt PROC C PUBLIC + hlt + ret +EfiHalt ENDP + +;VOID +;EfiWbinvd ( +; VOID +;) +EfiWbinvd PROC C PUBLIC + wbinvd + ret +EfiWbinvd ENDP + +;VOID +;EfiInvd ( +; VOID +;) +EfiInvd PROC C PUBLIC + invd + ret +EfiInvd ENDP + +;VOID +;EfiCpuid (IN UINT32 RegisterInEax, +; OUT EFI_CPUID_REGISTER *Reg OPTIONAL) +EfiCpuid PROC C PUBLIC + push ebp + mov ebp, esp + push ebx + push esi + push edi + pushad + + mov eax, dword ptr[ebp + 8] ;egisterInEax + cpuid + cmp dword ptr[ebp + 0Ch], 0 ; Reg + je @F + mov edi,dword ptr [ebp+0Ch] ; Reg + + mov dword ptr [edi],eax ; Reg->RegEax + mov dword ptr [edi+4],ebx ; Reg->RegEbx + mov dword ptr [edi+8],ecx ; Reg->RegEcx + mov dword ptr [edi+0Ch],edx ; Reg->RegEdx + +@@: + popad + pop edi + pop esi + pop ebx + pop ebp + + ret +EfiCpuid ENDP + + +;UINT64 +;EfiReadMsr ( +; IN UINT32 Index +; ); +EfiReadMsr PROC C PUBLIC + mov ecx, dword ptr [esp + 4]; Index + rdmsr + ret +EfiReadMsr ENDP + +;VOID +;EfiWriteMsr ( +; IN UINT32 Index, +; IN UINT64 Value +; ); +EfiWriteMsr PROC C PUBLIC + mov ecx, dword ptr [esp+4]; Index + mov eax, dword ptr [esp+8]; DWORD PTR Value[0] + mov edx, dword ptr [esp+0Ch]; DWORD PTR Value[4] + wrmsr + ret +EfiWriteMsr ENDP + +;UINT64 +;EfiReadTsc ( +; VOID +; ) +EfiReadTsc PROC C PUBLIC + rdtsc + ret +EfiReadTsc ENDP + +;VOID +;EfiDisableCache ( +; VOID +;) +EfiDisableCache PROC C PUBLIC + mov eax, cr0 + bswap eax + and al, 60h + cmp al, 60h + je @F + mov eax, cr0 + or eax, 060000000h + mov cr0, eax + wbinvd +@@: + ret +EfiDisableCache ENDP + +;VOID +;EfiEnableCache ( +; VOID +; ) +EfiEnableCache PROC C PUBLIC + wbinvd + mov eax, cr0 + and eax, 09fffffffh + mov cr0, eax + ret +EfiEnableCache ENDP + +;UINT32 +;EfiGetEflags ( +; VOID +; ) +EfiGetEflags PROC C PUBLIC + pushfd + pop eax + ret +EfiGetEflags ENDP + +;VOID +;EfiDisableInterrupts ( +; VOID +; ) +EfiDisableInterrupts PROC C PUBLIC + cli + ret +EfiDisableInterrupts ENDP + +;VOID +;EfiEnableInterrupts ( +; VOID +; ) +EfiEnableInterrupts PROC C PUBLIC + sti + ret +EfiEnableInterrupts ENDP + +;VOID +;EfiCpuidExt ( +; IN UINT32 RegisterInEax, +; IN UINT32 CacheLevel, +; OUT EFI_CPUID_REGISTER *Regs +; ) +EfiCpuidExt PROC C PUBLIC USES ebx edi esi + pushad + + mov eax, dword ptr [esp + 30h] ; RegisterInEax + mov ecx, dword ptr [esp + 34h] ; CacheLevel + cpuid + mov edi, dword ptr [esp + 38h] ; DWORD PTR Regs + + mov dword ptr [edi], eax ; Reg->RegEax + mov dword ptr [edi + 4], ebx ; Reg->RegEbx + mov dword ptr [edi + 8], ecx ; Reg->RegEcx + mov dword ptr [edi + 0Ch], edx ; Reg->RegEdx + + popad + ret +EfiCpuidExt ENDP + + END + diff --git a/Vlv2TbltDevicePkg/Library/CpuIA32Lib/IA32/CpuIA32.c b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/IA32/CpuIA32.c new file mode 100644 index 0000000000..aa1871850c --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/IA32/CpuIA32.c @@ -0,0 +1,182 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + CpuIA32.c + +Abstract: + +--*/ + +#include + +VOID +EfiHalt (VOID) +{ + __asm { + hlt + } +} + +VOID +EfiWbinvd (VOID) +{ + __asm { + wbinvd + } +} + +VOID +EfiInvd (VOID) +{ + __asm { + invd + } +} + +VOID +EfiCpuid (IN UINT32 RegisterInEax, + OUT EFI_CPUID_REGISTER *Reg OPTIONAL) +{ + __asm { + pushad + + mov eax, RegisterInEax + cpuid + cmp Reg, 0 + je _Exit + mov edi, DWORD PTR Reg + + mov DWORD PTR [edi].RegEax, eax ; Reg->RegEax + mov DWORD PTR [edi].RegEbx, ebx ; Reg->RegEbx + mov DWORD PTR [edi].RegEcx, ecx ; Reg->RegEcx + mov DWORD PTR [edi].RegEdx, edx ; Reg->RegEdx + +_Exit: + popad + } +} + +UINT64 +EfiReadMsr (IN UINT32 Index) +{ + __asm { + mov ecx, Index + rdmsr + } +} + +VOID +EfiWriteMsr ( + IN UINT32 Index, + IN UINT64 Value + ) +{ + __asm { + mov ecx, Index + mov eax, DWORD PTR Value[0] + mov edx, DWORD PTR Value[4] + wrmsr + } +} + +UINT64 +EfiReadTsc (VOID) +{ + __asm { + rdtsc + } +} + +VOID +EfiDisableCache (VOID) +{ + __asm { + mov eax, cr0 + bswap eax + and al, 60h + cmp al, 60h + je Exit + mov eax, cr0 + or eax, 060000000h + mov cr0, eax + wbinvd +Exit: + } +} + +VOID +EfiEnableCache (VOID) +{ + __asm { + wbinvd + mov eax, cr0 + and eax, 09fffffffh + mov cr0, eax + } +} + +UINT32 +EfiGetEflags ( + VOID + ) +{ + __asm { + pushfd + pop eax + } +} + +VOID +EfiDisableInterrupts (VOID) +{ + __asm { + cli + } +} + +VOID +EfiEnableInterrupts ( + VOID + ) +{ + __asm { + sti + } +} + +VOID +EfiCpuidExt ( + IN UINT32 RegisterInEax, + IN UINT32 CacheLevel, + OUT EFI_CPUID_REGISTER *Regs + ) +{ + __asm { + pushad + + mov eax, RegisterInEax + mov ecx, CacheLevel + cpuid + mov edi, DWORD PTR Regs + + mov DWORD PTR [edi].RegEax, eax ; Reg->RegEax + mov DWORD PTR [edi].RegEbx, ebx ; Reg->RegEbx + mov DWORD PTR [edi].RegEcx, ecx ; Reg->RegEcx + mov DWORD PTR [edi].RegEdx, edx ; Reg->RegEdx + + popad + } +} diff --git a/Vlv2TbltDevicePkg/Library/CpuIA32Lib/X64/Cpu.S b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/X64/Cpu.S new file mode 100644 index 0000000000..1eab73d17e --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/X64/Cpu.S @@ -0,0 +1,212 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +#* Module Name: +#* +#* Cpu.asm +#* +#* Abstract: +#* +#------------------------------------------------------------------------------ +##include + +.globl ASM_PFX(EfiHalt) +.globl ASM_PFX(EfiWbinvd) +.globl ASM_PFX(EfiInvd) +.globl ASM_PFX(EfiCpuid) +.globl ASM_PFX(EfiReadTsc) +.globl ASM_PFX(EfiDisableCache) +.globl ASM_PFX(EfiEnableCache) +.globl ASM_PFX(EfiReadMsr) +.globl ASM_PFX(EfiWriteMsr) +.globl ASM_PFX(EfiGetEflags) +.globl ASM_PFX(EfiDisableInterrupts) +.globl ASM_PFX(EfiEnableInterrupts) +.globl ASM_PFX(EfiCpuidExt) + +.text + + +#------------------------------------------------------------------------------ +# VOID +# EfiHalt ( +# VOID +# ) +#------------------------------------------------------------------------------ +ASM_PFX(EfiHalt): + hlt + retq + + +#------------------------------------------------------------------------------ +# VOID +# EfiWbinvd ( +# VOID +# ) +#------------------------------------------------------------------------------ +ASM_PFX(EfiWbinvd): + wbinvd + retq + + +#------------------------------------------------------------------------------ +# VOID +# EfiInvd ( +# VOID +# ) +#------------------------------------------------------------------------------ +ASM_PFX(EfiInvd): + invd + retq + +#------------------------------------------------------------------------------ +# VOID +# EfiCpuid ( +# IN UINT32 RegisterInEax, // rcx +# OUT EFI_CPUID_REGISTER *Reg OPTIONAL // rdx +# ) +#------------------------------------------------------------------------------ +ASM_PFX(EfiCpuid): + push %rbx + mov %rdx,%r8 + mov %rcx,%rax + cpuid + cmp $0x0,%r8 + je _Exit + mov %eax,(%r8) + mov %ebx,0x4(%r8) + mov %ecx,0x8(%r8) + mov %edx,0xc(%r8) +_Exit: + pop %rbx + retq + +#------------------------------------------------------------------------------ +# UINT64 +# EfiReadMsr ( +# IN UINT32 Index, // rcx +# ) +#------------------------------------------------------------------------------ +ASM_PFX(EfiReadMsr): + rdmsr + shl $0x20,%rdx + or %rdx,%rax + retq + +#------------------------------------------------------------------------------ +# VOID +# EfiWriteMsr ( +# IN UINT32 Index, // rcx +# IN UINT64 Value // rdx +# ) +#------------------------------------------------------------------------------ +ASM_PFX(EfiWriteMsr): + mov %rdx,%rax + sar $0x20,%rdx + wrmsr + retq + +#------------------------------------------------------------------------------ +# UINT64 +# EfiReadTsc ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_PFX(EfiReadTsc): + rdtsc + shl $0x20,%rax + shrd $0x20,%rdx,%rax + retq + +#------------------------------------------------------------------------------ +# VOID +# EfiDisableCache ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_PFX(EfiDisableCache): +# added a check to see if cache is already disabled. If it is, then skip. + mov %cr0,%rax + and $0x60000000,%rax + cmp $0x0,%rax + jne 1f + mov %cr0,%rax + or $0x60000000,%rax + mov %rax,%cr0 + wbinvd +1: + retq + +#------------------------------------------------------------------------------ +# VOID +# EfiEnableCache ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_PFX(EfiEnableCache): + wbinvd + mov %cr0,%rax + and $0xffffffff9fffffff,%rax + mov %rax,%cr0 + retq + +#------------------------------------------------------------------------------ +# UINTN +# EfiGetEflags ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_PFX(EfiGetEflags): + pushfq + pop %rax + retq + +#------------------------------------------------------------------------------ +# VOID +# EfiDisableInterrupts ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_PFX(EfiDisableInterrupts): + cli + ret + +#------------------------------------------------------------------------------ +# VOID +# EfiEnableInterrupts ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_PFX(EfiEnableInterrupts): + sti + ret +#------------------------------------------------------------------------------ +# VOID +# EfiCpuidExt ( +# IN UINT32 RegisterInEax, +# IN UINT32 CacheLevel, +# OUT EFI_CPUID_REGISTER *Regs +# ) +#------------------------------------------------------------------------------ +ASM_PFX(EfiCpuidExt): + push %rbx + mov %rcx,%rax + mov %rdx,%rcx + cpuid + mov %eax,(%r8) + mov %ebx,0x4(%r8) + mov %ecx,0x8(%r8) + mov %edx,0xc(%r8) + pop %rbx + retq diff --git a/Vlv2TbltDevicePkg/Library/CpuIA32Lib/X64/Cpu.asm b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/X64/Cpu.asm new file mode 100644 index 0000000000..d921132137 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/CpuIA32Lib/X64/Cpu.asm @@ -0,0 +1,227 @@ + +TITLE Cpu.asm: Assembly code for the x64 resources + +; +; This file contains an 'Intel Sample Driver' and is +; licensed for Intel CPUs and chipsets under the terms of your +; license agreement with Intel or your vendor. This file may +; be modified by the user, subject to additional terms of the +; license agreement +; +; +; Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +; +; This program and the accompanying materials are licensed and made available under +; the terms and conditions of the BSD License that accompanies this distribution. +; The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; +; +; +; +;* Module Name: +;* +;* Cpu.asm +;* +;* Abstract: +;* +;------------------------------------------------------------------------------ + +text SEGMENT + + +;------------------------------------------------------------------------------ +; VOID +; EfiHalt ( +; VOID +; ) +;------------------------------------------------------------------------------ +EfiHalt PROC PUBLIC + hlt + ret +EfiHalt ENDP + + +;------------------------------------------------------------------------------ +; VOID +; EfiWbinvd ( +; VOID +; ) +;------------------------------------------------------------------------------ +EfiWbinvd PROC PUBLIC + wbinvd + ret +EfiWbinvd ENDP + + +;------------------------------------------------------------------------------ +; VOID +; EfiInvd ( +; VOID +; ) +;------------------------------------------------------------------------------ +EfiInvd PROC PUBLIC + invd + ret +EfiInvd ENDP + +;------------------------------------------------------------------------------ +; VOID +; EfiCpuid ( +; IN UINT32 RegisterInEax, // rcx +; OUT EFI_CPUID_REGISTER *Reg OPTIONAL // rdx +; ) +;------------------------------------------------------------------------------ +EfiCpuid PROC PUBLIC + push rbx + + mov r8, rdx ; r8 = *Reg + mov rax, rcx ; RegisterInEax + cpuid + cmp r8, 0 + je _Exit + mov [r8 + 0], eax ; Reg->RegEax + mov [r8 + 4], ebx ; Reg->RegEbx + mov [r8 + 8], ecx ; Reg->RegEcx + mov [r8 + 12], edx ; Reg->RegEdx + +_Exit: + pop rbx + ret +EfiCpuid ENDP + +;------------------------------------------------------------------------------ +; UINT64 +; EfiReadMsr ( +; IN UINT32 Index, // rcx +; ) +;------------------------------------------------------------------------------ +EfiReadMsr PROC PUBLIC + rdmsr + sal rdx, 32 ; edx:eax -> rax + or rax, rdx ; rax = edx:eax + ret +EfiReadMsr ENDP + +;------------------------------------------------------------------------------ +; VOID +; EfiWriteMsr ( +; IN UINT32 Index, // rcx +; IN UINT64 Value // rdx +; ) +;------------------------------------------------------------------------------ +EfiWriteMsr PROC PUBLIC + mov rax, rdx ; rdx = Value + sar rdx, 32 ; convert rdx to edx upper 32-bits + wrmsr ; wrmsr[ecx] result = edx:eax + ret +EfiWriteMsr ENDP + + +;------------------------------------------------------------------------------ +; UINT64 +; EfiReadTsc ( +; VOID +; ); +;------------------------------------------------------------------------------ +EfiReadTsc PROC PUBLIC + rdtsc + shl rax, 32 + shrd rax, rdx, 32 + ret +EfiReadTsc ENDP + +;------------------------------------------------------------------------------ +; VOID +; EfiDisableCache ( +; VOID +; ); +;------------------------------------------------------------------------------ +EfiDisableCache PROC PUBLIC +; added a check to see if cache is already disabled. If it is, then skip. + mov rax, cr0 + and rax, 060000000h + cmp rax, 0 + jne @f + mov rax, cr0 + or rax, 060000000h + mov cr0, rax + wbinvd +@@: + ret +EfiDisableCache ENDP + +;------------------------------------------------------------------------------ +; VOID +; EfiEnableCache ( +; VOID +; ); +;------------------------------------------------------------------------------ +EfiEnableCache PROC PUBLIC + wbinvd + mov rax, cr0 + and rax, 09fffffffh + mov cr0, rax + ret +EfiEnableCache ENDP + +;------------------------------------------------------------------------------ +; UINTN +; EfiGetEflags ( +; VOID +; ); +;------------------------------------------------------------------------------ +EfiGetEflags PROC PUBLIC + pushfq + pop rax + ret +EfiGetEflags ENDP + +;------------------------------------------------------------------------------ +; VOID +; EfiDisableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +EfiDisableInterrupts PROC PUBLIC + cli + ret +EfiDisableInterrupts ENDP + +;------------------------------------------------------------------------------ +; VOID +; EfiEnableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +EfiEnableInterrupts PROC PUBLIC + sti + ret +EfiEnableInterrupts ENDP +;------------------------------------------------------------------------------ +; VOID +; EfiCpuidExt ( +; IN UINT32 RegisterInEax, +; IN UINT32 CacheLevel, +; OUT EFI_CPUID_REGISTER *Regs +; ) +;------------------------------------------------------------------------------ +EfiCpuidExt PROC PUBLIC + push rbx + mov rax, rcx ; rax = RegisterInEax + mov rcx, rdx ; rcx = CacheLevel + + cpuid + mov [r8 + 0 ], eax ; Reg->RegEax + mov [r8 + 4 ], ebx ; Reg->RegEbx + mov [r8 + 8 ], ecx ; Reg->RegEcx + mov [r8 + 12], edx ; Reg->RegEdx + + pop rbx + ret +EfiCpuidExt ENDP +END diff --git a/Vlv2TbltDevicePkg/Library/EfiRegTableLib/EfiRegTableLib.c b/Vlv2TbltDevicePkg/Library/EfiRegTableLib/EfiRegTableLib.c new file mode 100644 index 0000000000..fa94cc74e8 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/EfiRegTableLib/EfiRegTableLib.c @@ -0,0 +1,287 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + EfiRegTableLib.c + +Abstract: + + Lib function for table driven register initialization. + +Revision History + +--*/ + +#include +#include + +// +// Local Functions +// + +/** + Local worker function to process PCI_WRITE table entries. Performs write and + may also call BootScriptSave protocol if indicated in the Entry flags + + @param Entry A pointer to the PCI_WRITE entry to process + + @param PciRootBridgeIo A pointer to the instance of PciRootBridgeIo that is used + when processing the entry. + + @retval Nothing. + +**/ +STATIC +VOID +PciWrite ( + EFI_REG_TABLE_PCI_WRITE *Entry, + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo + ) +{ + EFI_STATUS Status; + + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (OPCODE_EXTRA_DATA (Entry->OpCode)), + (UINT64) Entry->PciAddress, + 1, + &Entry->Data + ); + ASSERT_EFI_ERROR (Status); + + if (OPCODE_FLAGS (Entry->OpCode) & OPCODE_FLAG_S3SAVE) { + Status = S3BootScriptSavePciCfgWrite ( + (EFI_BOOT_SCRIPT_WIDTH) (OPCODE_EXTRA_DATA (Entry->OpCode)), + (UINT64) Entry->PciAddress, + 1, + &Entry->Data + ); + ASSERT_EFI_ERROR (Status); + } +} + +/** + Local worker function to process PCI_READ_MODIFY_WRITE table entries. + Performs RMW write and may also call BootScriptSave protocol if indicated in + the Entry flags. + + @param Entry A pointer to the PCI_READ_MODIFY_WRITE entry to process. + + @param PciRootBridgeIo A pointer to the instance of PciRootBridgeIo that is used + when processing the entry. + + @retval Nothing. + +**/ +STATIC +VOID +PciReadModifyWrite ( + EFI_REG_TABLE_PCI_READ_MODIFY_WRITE *Entry, + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo + ) +{ + EFI_STATUS Status; + UINT32 TempData; + + Status = PciRootBridgeIo->Pci.Read ( + PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (OPCODE_EXTRA_DATA (Entry->OpCode)), + (UINT64) Entry->PciAddress, + 1, + &TempData + ); + ASSERT_EFI_ERROR (Status); + + Entry->OrMask &= Entry->AndMask; + TempData &= ~Entry->AndMask; + TempData |= Entry->OrMask; + + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (OPCODE_EXTRA_DATA (Entry->OpCode)), + (UINT64) Entry->PciAddress, + 1, + &TempData + ); + ASSERT_EFI_ERROR (Status); + + if (OPCODE_FLAGS (Entry->OpCode) & OPCODE_FLAG_S3SAVE) { + Status = S3BootScriptSavePciCfgReadWrite ( + (EFI_BOOT_SCRIPT_WIDTH) (OPCODE_EXTRA_DATA (Entry->OpCode)), + (UINT64) Entry->PciAddress, + &Entry->OrMask, + &Entry->AndMask + ); + ASSERT_EFI_ERROR (Status); + } +} + +/** + Local worker function to process MEM_READ_MODIFY_WRITE table entries. + Performs RMW write and may also call BootScriptSave protocol if indicated in + the Entry flags. + + @param Entry A pointer to the MEM_READ_MODIFY_WRITE entry to process. + + @param PciRootBridgeIo A pointer to the instance of PciRootBridgeIo that is used + when processing the entry. + + @retval Nothing. + +**/ +STATIC +VOID +MemReadModifyWrite ( + EFI_REG_TABLE_MEM_READ_MODIFY_WRITE *Entry, + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo + ) +{ + EFI_STATUS Status; + UINT32 TempData; + + Status = PciRootBridgeIo->Mem.Read ( + PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (OPCODE_EXTRA_DATA (Entry->OpCode)), + (UINT64) Entry->MemAddress, + 1, + &TempData + ); + ASSERT_EFI_ERROR (Status); + + Entry->OrMask &= Entry->AndMask; + TempData &= ~Entry->AndMask; + TempData |= Entry->OrMask; + + Status = PciRootBridgeIo->Mem.Write ( + PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (OPCODE_EXTRA_DATA (Entry->OpCode)), + (UINT64) Entry->MemAddress, + 1, + &TempData + ); + ASSERT_EFI_ERROR (Status); + + if (OPCODE_FLAGS (Entry->OpCode) & OPCODE_FLAG_S3SAVE) { + Status = S3BootScriptSaveMemReadWrite ( + (EFI_BOOT_SCRIPT_WIDTH) (OPCODE_EXTRA_DATA (Entry->OpCode)), + Entry->MemAddress, + &Entry->OrMask, + &Entry->AndMask + ); + ASSERT_EFI_ERROR (Status); + } +} + +// +// Exported functions +// + +/** + Processes register table assuming which may contain PCI, IO, MEM, and STALL + entries. + + No parameter checking is done so the caller must be careful about omitting + values for PciRootBridgeIo or CpuIo parameters. If the regtable does + not contain any PCI accesses, it is safe to omit the PciRootBridgeIo (supply + NULL). If the regtable does not contain any IO or Mem entries, it is safe to + omit the CpuIo (supply NULL). + + The RegTableEntry parameter is not checked, but is required. + + gBS is assumed to have been defined and is used when processing stalls. + + The function processes each entry sequentially until an OP_TERMINATE_TABLE + entry is encountered. + + @param RegTableEntry A pointer to the register table to process + + @param PciRootBridgeIo A pointer to the instance of PciRootBridgeIo that is used + when processing PCI table entries + + @param CpuIo A pointer to the instance of CpuIo that is used when processing IO and + MEM table entries + + @retval Nothing. + +**/ +VOID +ProcessRegTablePci ( + EFI_REG_TABLE *RegTableEntry, + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + EFI_CPU_IO_PROTOCOL *CpuIo + ) +{ + while (OPCODE_BASE (RegTableEntry->Generic.OpCode) != OP_TERMINATE_TABLE) { + switch (OPCODE_BASE (RegTableEntry->Generic.OpCode)) { + case OP_PCI_WRITE: + PciWrite ((EFI_REG_TABLE_PCI_WRITE *) RegTableEntry, PciRootBridgeIo); + break; + + case OP_PCI_READ_MODIFY_WRITE: + PciReadModifyWrite ((EFI_REG_TABLE_PCI_READ_MODIFY_WRITE *) RegTableEntry, PciRootBridgeIo); + break; + + case OP_MEM_READ_MODIFY_WRITE: + MemReadModifyWrite ((EFI_REG_TABLE_MEM_READ_MODIFY_WRITE *) RegTableEntry, PciRootBridgeIo); + break; + + default: + DEBUG ((EFI_D_ERROR, "RegTable ERROR: Unknown RegTable OpCode (%x)\n", OPCODE_BASE (RegTableEntry->Generic.OpCode))); + ASSERT (0); + break; + } + + RegTableEntry++; + } +} + +/** + Processes register table assuming which may contain IO, MEM, and STALL + entries, but must NOT contain any PCI entries. Any PCI entries cause an + ASSERT in a DEBUG build and are skipped in a free build. + + No parameter checking is done. Both RegTableEntry and CpuIo parameters are + required. + + gBS is assumed to have been defined and is used when processing stalls. + + The function processes each entry sequentially until an OP_TERMINATE_TABLE + entry is encountered. + + @param RegTableEntry A pointer to the register table to process + + @param CpuIo A pointer to the instance of CpuIo that is used when processing IO and + MEM table entries + + @retval Nothing. + +**/ +VOID +ProcessRegTableCpu ( + EFI_REG_TABLE *RegTableEntry, + EFI_CPU_IO_PROTOCOL *CpuIo + ) +{ + while (OPCODE_BASE (RegTableEntry->Generic.OpCode) != OP_TERMINATE_TABLE) { + switch (OPCODE_BASE (RegTableEntry->Generic.OpCode)) { + default: + DEBUG ((EFI_D_ERROR, "RegTable ERROR: Unknown RegTable OpCode (%x)\n", OPCODE_BASE (RegTableEntry->Generic.OpCode))); + ASSERT (0); + break; + } + + RegTableEntry++; + } +} diff --git a/Vlv2TbltDevicePkg/Library/EfiRegTableLib/EfiRegTableLib.inf b/Vlv2TbltDevicePkg/Library/EfiRegTableLib/EfiRegTableLib.inf new file mode 100644 index 0000000000..9a6b29bf9f --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/EfiRegTableLib/EfiRegTableLib.inf @@ -0,0 +1,52 @@ +# +# +#/*++ +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +# +# Module Name: +# +# EfiRegTableLib.inf +# +# Abstract: +# +# Component description file. +# +#--*/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = EfiRegTableLib + FILE_GUID = 98546145-64F1-4d2e-814F-6BF963DB7930 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = EfiRegTableLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + EfiRegTableLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + + +[LibraryClasses] + diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c new file mode 100644 index 0000000000..afb12c90fb --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.c @@ -0,0 +1,467 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "SpiChipDefinitions.h" + +UINTN FlashDeviceBase = FLASH_DEVICE_BASE_ADDRESS; + +EFI_SPI_PROTOCOL *mSpiProtocol = NULL; + +EFI_STATUS +SpiFlashErase ( + UINT8 *BaseAddress, + UINTN NumBytes + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT32 SectorSize; + UINT32 SpiAddress; + + SpiAddress = (UINT32)(UINTN)(BaseAddress) - (UINT32)FlashDeviceBase; + SectorSize = SECTOR_SIZE_4KB; + while ( (NumBytes > 0) && (NumBytes <= MAX_FWH_SIZE) ) { + Status = mSpiProtocol->Execute ( + mSpiProtocol, + SPI_SERASE, + SPI_WREN, + FALSE, + TRUE, + FALSE, + (UINT32) SpiAddress, + 0, + NULL, + EnumSpiRegionBios + ); + if (EFI_ERROR (Status)) { + break; + } + SpiAddress += SectorSize; + NumBytes -= SectorSize; + } + + return Status; +} + + +EFI_STATUS +SpiFlashBlockErase ( + UINT8 *BaseAddress, + UINTN NumBytes + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT32 SectorSize; + UINT32 SpiAddress; + + SpiAddress = (UINT32)(UINTN)(BaseAddress) - (UINT32)FlashDeviceBase; + SectorSize = SECTOR_SIZE_64KB; + while ( (NumBytes > 0) && (NumBytes <= MAX_FWH_SIZE) ) { + Status = mSpiProtocol->Execute ( + mSpiProtocol, + SPI_BERASE, + SPI_WREN, + FALSE, + TRUE, + FALSE, + (UINT32) SpiAddress, + 0, + NULL, + EnumSpiRegionBios + ); + if (EFI_ERROR (Status)) { + break; + } + SpiAddress += SectorSize; + NumBytes -= SectorSize; + } + + return Status; +} + + +static +EFI_STATUS +SpiFlashWrite ( + UINT8 *DstBufferPtr, + UINT8 *Byte, + IN UINTN Length + ) +{ + EFI_STATUS Status; + UINT32 NumBytes = (UINT32)Length; + UINT8* pBuf8 = Byte; + UINT32 SpiAddress; + + SpiAddress = (UINT32)(UINTN)(DstBufferPtr) - (UINT32)FlashDeviceBase; + Status = mSpiProtocol->Execute ( + mSpiProtocol, + SPI_PROG, + SPI_WREN, + TRUE, + TRUE, + TRUE, + (UINT32)SpiAddress, + NumBytes, + pBuf8, + EnumSpiRegionBios + ); + return Status; +} + +/** + Read the Serial Flash Status Registers. + + @param SpiStatus Pointer to a caller-allocated UINT8. On successful return, it contains the + status data read from the Serial Flash Status Register. + + + @retval EFI_SUCCESS Operation success, status is returned in SpiStatus. + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and the operation failed. + +**/ +EFI_STATUS +ReadStatusRegister ( + UINT8 *SpiStatus + ) +{ + EFI_STATUS Status; + + Status = mSpiProtocol->Execute ( + mSpiProtocol, + SPI_RDSR, + SPI_WREN, + TRUE, + FALSE, + FALSE, + 0, + 1, + SpiStatus, + EnumSpiRegionBios + ); + return Status; +} + +EFI_STATUS +SpiFlashLock ( + IN UINT8 *BaseAddress, + IN UINTN NumBytes, + IN BOOLEAN Lock + ) +{ + EFI_STATUS Status; + UINT8 SpiData; + UINT8 SpiStatus; + + if (Lock) { + SpiData = SF_SR_WPE; + } else { + SpiData = 0; + } + + // + // Always disable block protection to workaround tool issue. + // Feature may be re-enabled in a future bios. + // + SpiData = 0; + Status = mSpiProtocol->Execute ( + mSpiProtocol, + SPI_WRSR, + SPI_EWSR, + TRUE, + TRUE, + TRUE, + 0, + 1, + &SpiData, + EnumSpiRegionBios + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = ReadStatusRegister (&SpiStatus); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((SpiStatus & SpiData) != SpiData) { + Status = EFI_DEVICE_ERROR; + } + + return Status; +} + + +/** + Read NumBytes bytes of data from the address specified by + PAddress into Buffer. + + @param[in] PAddress The starting physical address of the read. + @param[in,out] NumBytes On input, the number of bytes to read. On output, the number + of bytes actually read. + @param[out] Buffer The destination data buffer for the read. + + @retval EFI_SUCCESS. Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +LibFvbFlashDeviceRead ( + IN UINTN PAddress, + IN OUT UINTN *NumBytes, + OUT UINT8 *Buffer + ) +{ + CopyMem(Buffer, (VOID*)PAddress, *NumBytes); + return EFI_SUCCESS; +} + + +/** + Write NumBytes bytes of data from Buffer to the address specified by + PAddresss. + + @param[in] PAddress The starting physical address of the write. + @param[in,out] NumBytes On input, the number of bytes to write. On output, + the actual number of bytes written. + @param[in] Buffer The source data buffer for the write. + + @retval EFI_SUCCESS. Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +LibFvbFlashDeviceWrite ( + IN UINTN PAddress, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ +EFI_STATUS Status; + Status = SpiFlashWrite((UINT8 *)PAddress, Buffer, *NumBytes); + return Status; +} + + +/** + Erase the block staring at PAddress. + + @param[in] PAddress The starting physical address of the block to be erased. + This library assume that caller garantee that the PAddress + is at the starting address of this block. + @param[in] LbaLength The length of the logical block to be erased. + + @retval EFI_SUCCESS. Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +LibFvbFlashDeviceBlockErase ( + IN UINTN PAddress, + IN UINTN LbaLength + ) +{ + EFI_STATUS Status; + Status = SpiFlashBlockErase((UINT8 *)PAddress, LbaLength); + + return Status; +} + + +/** + Lock or unlock the block staring at PAddress. + + @param[in] PAddress The starting physical address of region to be (un)locked. + @param[in] LbaLength The length of the logical block to be erased. + @param[in] Lock TRUE to lock. FALSE to unlock. + + @retval EFI_SUCCESS. Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +LibFvbFlashDeviceBlockLock ( + IN UINTN PAddress, + IN UINTN LbaLength, + IN BOOLEAN Lock + ) +{ + EFI_STATUS Status; + + Status = SpiFlashLock((UINT8*)PAddress, LbaLength, Lock); + return Status; +} + +VOID +EFIAPI +LibFvbFlashDeviceVirtualAddressChangeNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + gRT->ConvertPointer (0, (VOID **) &mSpiProtocol); + gRT->ConvertPointer (0, (VOID **) &FlashDeviceBase); +} + + +/** + The library constructuor. + + The function does the necessary initialization work for this library + instance. Please put all initialization works in it. + + @param[in] ImageHandle The firmware allocated handle for the UEFI image. + @param[in] SystemTable A pointer to the EFI system table. + + @retval EFI_SUCCESS The function always return EFI_SUCCESS for now. + It will ASSERT on error for debug version. + @retval EFI_ERROR Please reference LocateProtocol for error code details. + +**/ +EFI_STATUS +EFIAPI +LibFvbFlashDeviceSupportInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + UINT8 SfId[3]; + UINT8 FlashIndex; + UINT8 SpiReadError; + UINT8 SpiNotMatchError; + EFI_SMM_BASE2_PROTOCOL *SmmBase; + BOOLEAN InSmm; + + SpiReadError = 0x00; + SpiNotMatchError = 0x00; + + InSmm = FALSE; + Status = gBS->LocateProtocol ( + &gEfiSmmBase2ProtocolGuid, + NULL, + (void **)&SmmBase + ); + if (!EFI_ERROR(Status)) { + Status = SmmBase->InSmm(SmmBase, &InSmm); + if (EFI_ERROR(Status)) { + InSmm = FALSE; + } + } + + if (!InSmm) { + Status = gBS->LocateProtocol ( + &gEfiSpiProtocolGuid, + NULL, + (VOID **)&mSpiProtocol + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + LibFvbFlashDeviceVirtualAddressChangeNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &Event + ); + ASSERT_EFI_ERROR (Status); + } else { + Status = gBS->LocateProtocol ( + &gEfiSmmSpiProtocolGuid, + NULL, + (VOID **)&mSpiProtocol + ); + ASSERT_EFI_ERROR (Status); + } + + + for (FlashIndex = EnumSpiFlashW25Q64; FlashIndex < EnumSpiFlashMax; FlashIndex++) { + Status = mSpiProtocol->Init (mSpiProtocol, &(mInitTable[FlashIndex])); + if (!EFI_ERROR (Status)) { + // + // Read Vendor/Device IDs to check if the driver supports the Serial Flash device. + // + Status = mSpiProtocol->Execute ( + mSpiProtocol, + SPI_READ_ID, + SPI_WREN, + TRUE, + FALSE, + FALSE, + 0, + 3, + SfId, + EnumSpiRegionAll + ); + if (!EFI_ERROR (Status)) { + if ((SfId[0] == mInitTable[FlashIndex].VendorId) && + (SfId[1] == mInitTable[FlashIndex].DeviceId0) && + (SfId[2] == mInitTable[FlashIndex].DeviceId1)) { + // + // Found a matching SPI device, FlashIndex now contains flash device. + // + DEBUG ((EFI_D_ERROR, "OK - Found SPI Flash Type in SPI Flash Driver, Device Type ID 0 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId0)); + DEBUG ((EFI_D_ERROR, "Device Type ID 1 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId1)); + + if (mInitTable[FlashIndex].BiosStartOffset == (UINTN) (-1)) { + DEBUG ((EFI_D_ERROR, "ERROR - The size of BIOS image is bigger than SPI Flash device!\n")); + CpuDeadLoop (); + } + break; + } else { + SpiNotMatchError++; + } + } else { + SpiReadError++; + } + } + } + + DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2])); + + if (FlashIndex < EnumSpiFlashMax) { + return EFI_SUCCESS; + } else { + if (SpiReadError != 0) { + DEBUG ((EFI_D_ERROR, "ERROR - SPI Read ID execution failed! Error Count = %d\n", SpiReadError)); + } + else { + if (SpiNotMatchError != 0) { + DEBUG ((EFI_D_ERROR, "ERROR - No supported SPI flash chip found! Error Count = %d\n", SpiNotMatchError)); + DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2])); + } + } + return EFI_UNSUPPORTED; + } +} + diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf new file mode 100644 index 0000000000..423490ecc1 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/FlashDeviceLib.inf @@ -0,0 +1,50 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# + + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FlashDeviceLib + FILE_GUID = E38A1C3C-928C-4bf7-B6C1-7F0EF163FAA5 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = FlashDeviceLib | DXE_SMM_DRIVER DXE_RUNTIME_DRIVER + CONSTRUCTOR = LibFvbFlashDeviceSupportInit + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + FlashDeviceLib.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + +[LibraryClasses] + DebugLib + +[Protocols] + gEfiSpiProtocolGuid + gEfiSmmSpiProtocolGuid + gEfiSmmBase2ProtocolGuid + diff --git a/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h new file mode 100644 index 0000000000..15bd1e0254 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/FlashDeviceLib/SpiChipDefinitions.h @@ -0,0 +1,840 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +**/ + +#include + +#define FLASH_SIZE 0x300000 +#define FLASH_DEVICE_BASE_ADDRESS (0xFFFFFFFF-FLASH_SIZE+1) + +// +// Serial Flash device initialization data table provided to the +// Intel(R) SPI Host Controller Compatibility Interface. +// +SPI_INIT_TABLE mInitTable[] = { + { + SF_VENDOR_ID_WINBOND, // VendorId + SF_DEVICE_ID0_W25QXX, // DeviceId 0 + SF_DEVICE_ID1_W25Q64, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Enable Write Status Register + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeRead, SF_INST_SFDP, EnumSpiCycle50MHz, EnumSpiOperationDiscoveryParameters}, // Opcode 3: Serial Flash Discovery Parameters + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((WINBOND_W25Q64_SIZE >= FLASH_SIZE) ? WINBOND_W25Q64_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_ATMEL, // VendorId + SF_DEVICE_ID0_AT25DF321A, // DeviceId 0 + SF_DEVICE_ID1_AT25DF321A, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR). + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (32KB) + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((ATMEL_AT25DF321A_SIZE >= FLASH_SIZE) ? ATMEL_AT25DF321A_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_ATMEL, // VendorId + SF_DEVICE_ID0_AT26DF321, // DeviceId 0 + SF_DEVICE_ID1_AT26DF321, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR). + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (32KB) + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((ATMEL_AT26DF321_SIZE >= FLASH_SIZE) ? ATMEL_AT26DF321_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_ATMEL, // VendorId + SF_DEVICE_ID0_AT25DF641, // DeviceId 0 + SF_DEVICE_ID1_AT25DF641, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR). + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (32KB) + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((ATMEL_AT25DF641_SIZE >= FLASH_SIZE) ? ATMEL_AT25DF641_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_WINBOND, // VendorId + SF_DEVICE_ID0_W25QXX, // DeviceId 0 + SF_DEVICE_ID1_W25Q16, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Enable Write Status Register + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeRead, SF_INST_SFDP, EnumSpiCycle50MHz, EnumSpiOperationDiscoveryParameters}, // Opcode 3: Serial Flash Discovery Parameters + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((WINBOND_W25Q16_SIZE >= FLASH_SIZE) ? WINBOND_W25Q16_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_WINBOND, // VendorId + SF_DEVICE_ID0_W25QXX, // DeviceId 0 + SF_DEVICE_ID1_W25Q32, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Enable Write Status Register. + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeRead, SF_INST_SFDP, EnumSpiCycle50MHz, EnumSpiOperationDiscoveryParameters}, // Opcode 3: Serial Flash Discovery Parameters + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((WINBOND_W25Q32_SIZE >= FLASH_SIZE) ? WINBOND_W25Q32_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_WINBOND, // VendorId + SF_DEVICE_ID0_W25XXX, // DeviceId 0 + SF_DEVICE_ID1_W25X32, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Enable Write Status Register + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeRead, SF_INST_SFDP, EnumSpiCycle50MHz, EnumSpiOperationDiscoveryParameters}, // Opcode 3: Serial Flash Discovery Parameters + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((WINBOND_W25X32_SIZE >= FLASH_SIZE) ? WINBOND_W25X32_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_WINBOND, // VendorId + SF_DEVICE_ID0_W25XXX, // DeviceId 0 + SF_DEVICE_ID1_W25X64, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Enable Write Status Register + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeRead, SF_INST_SFDP, EnumSpiCycle50MHz, EnumSpiOperationDiscoveryParameters}, // Opcode 3: Serial Flash Discovery Parameters + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((WINBOND_W25X64_SIZE >= FLASH_SIZE) ? WINBOND_W25X64_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_WINBOND, // VendorId + SF_DEVICE_ID0_W25QXX, // DeviceId 0 + SF_DEVICE_ID1_W25Q128, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Enable Write Status Register + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeRead, SF_INST_SFDP, EnumSpiCycle50MHz, EnumSpiOperationDiscoveryParameters}, // Opcode 3: Serial Flash Discovery Parameters + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((WINBOND_W25Q128_SIZE >= FLASH_SIZE) ? WINBOND_W25Q128_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_MACRONIX, // VendorId + SF_DEVICE_ID0_MX25LXX, // DeviceId 0 + SF_DEVICE_ID1_MX25L16, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Write Enable (this part doesn't support EWSR). + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeRead, SF_INST_SFDP, EnumSpiCycle50MHz, EnumSpiOperationDiscoveryParameters}, // Opcode 3: Serial Flash Discovery Parameters + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((MACRONIX_MX25L16_SIZE >= FLASH_SIZE) ? MACRONIX_MX25L16_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_MACRONIX, // VendorId + SF_DEVICE_ID0_MX25LXX, // DeviceId 0 + SF_DEVICE_ID1_MX25L32, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Write Enable (this part doesn't support EWSR). + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeRead, SF_INST_SFDP, EnumSpiCycle50MHz, EnumSpiOperationDiscoveryParameters}, // Opcode 3: Serial Flash Discovery Parameters + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((MACRONIX_MX25L32_SIZE >= FLASH_SIZE) ? MACRONIX_MX25L32_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_MACRONIX, // VendorId + SF_DEVICE_ID0_MX25LXX, // DeviceId 0 + SF_DEVICE_ID1_MX25L64, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Write Enable (this part doesn't support EWSR) + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeRead, SF_INST_SFDP, EnumSpiCycle50MHz, EnumSpiOperationDiscoveryParameters}, // Opcode 3: Serial Flash Discovery Parameters + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((MACRONIX_MX25L64_SIZE >= FLASH_SIZE) ? MACRONIX_MX25L64_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_MACRONIX, // VendorId + SF_DEVICE_ID0_MX25LXX, // DeviceId 0 + SF_DEVICE_ID1_MX25L128, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Write Enable (this part doesn't support EWSR) + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeRead, SF_INST_SFDP, EnumSpiCycle50MHz, EnumSpiOperationDiscoveryParameters}, // Opcode 3: Serial Flash Discovery Parameters + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((MACRONIX_MX25L128_SIZE >= FLASH_SIZE) ? MACRONIX_MX25L128_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_MACRONIX, // VendorId + SF_DEVICE_ID0_MX25UXX, // DeviceId 0 + SF_DEVICE_ID1_MX25U6435F, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Write Enable (this part doesn't support EWSR) + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeRead, SF_INST_SFDP, EnumSpiCycle50MHz, EnumSpiOperationDiscoveryParameters}, // Opcode 3: Serial Flash Discovery Parameters + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((MACRONIX_MX25U64_SIZE >= FLASH_SIZE) ? MACRONIX_MX25U64_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_SST, // VendorId + SF_DEVICE_ID0_SST25VF0XXX,// DeviceId 0 + SF_DEVICE_ID1_SST25VF016B,// DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Enable Write Status Register + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle20MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (32KB) + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((SST_SST25VF016B_SIZE >= FLASH_SIZE) ? SST_SST25VF016B_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_SST, // VendorId + SF_DEVICE_ID0_SST25VF0XXX,// DeviceId 0 + SF_DEVICE_ID1_SST25VF064C,// DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_EWSR // Prefix Opcode 1: Enable Write Status Register + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle20MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (32KB) + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((SST_SST25VF064C_SIZE >= FLASH_SIZE) ? SST_SST25VF064C_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + // + // Minnow2 SPI type + // + SF_VENDOR_ID_NUMONYX, // VendorId + SF_DEVICE_ID0_N25Q064, // DeviceId 0 + SF_DEVICE_ID1_N25Q064, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR) + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle20MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle20MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle20MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle20MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle20MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle20MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle20MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle20MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((NUMONYX_N25Q064_SIZE >= FLASH_SIZE) ? NUMONYX_N25Q064_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_NUMONYX, // VendorId + SF_DEVICE_ID0_M25PXXX, // DeviceId 0 + SF_DEVICE_ID1_M25PX16, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR). + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((NUMONYX_M25PX16_SIZE >= FLASH_SIZE) ? NUMONYX_M25PX16_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_NUMONYX, // VendorId + SF_DEVICE_ID0_N25QXXX, // DeviceId 0 + SF_DEVICE_ID1_N25Q032, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR). + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((NUMONYX_N25Q032_SIZE >= FLASH_SIZE) ? NUMONYX_N25Q032_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_NUMONYX, // VendorId + SF_DEVICE_ID0_M25PXXX, // DeviceId 0 + SF_DEVICE_ID1_M25PX32, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR). + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((NUMONYX_M25PX32_SIZE >= FLASH_SIZE) ? NUMONYX_M25PX32_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_NUMONYX, // VendorId + SF_DEVICE_ID0_M25PXXX, // DeviceId 0 + SF_DEVICE_ID1_M25PX64, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR) + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((NUMONYX_M25PX64_SIZE >= FLASH_SIZE) ? NUMONYX_M25PX64_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_NUMONYX, // VendorId + SF_DEVICE_ID0_N25QXXX, // DeviceId 0 + SF_DEVICE_ID1_N25Q128, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR) + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((NUMONYX_N25Q128_SIZE >= FLASH_SIZE) ? NUMONYX_N25Q128_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_EON, // VendorId + SF_DEVICE_ID0_EN25QXX, // DeviceId 0 + SF_DEVICE_ID1_EN25Q16, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR) + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((EON_EN25Q16_SIZE >= FLASH_SIZE) ? EON_EN25Q16_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_EON, // VendorId + SF_DEVICE_ID0_EN25QXX, // DeviceId 0 + SF_DEVICE_ID1_EN25Q32, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR) + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle33MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((EON_EN25Q32_SIZE >= FLASH_SIZE) ? EON_EN25Q32_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_EON, // VendorId + SF_DEVICE_ID0_EN25QXX, // DeviceId 0 + SF_DEVICE_ID1_EN25Q64, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR). + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((EON_EN25Q64_SIZE >= FLASH_SIZE) ? EON_EN25Q64_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_EON, // VendorId + SF_DEVICE_ID0_EN25QXX, // DeviceId 0 + SF_DEVICE_ID1_EN25Q128, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR) + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((EON_EN25Q128_SIZE >= FLASH_SIZE) ? EON_EN25Q128_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + }, + { + SF_VENDOR_ID_AMIC, // VendorId + SF_DEVICE_ID0_A25L016, // DeviceId 0 + SF_DEVICE_ID1_A25L016, // DeviceId 1 + { + SF_INST_WREN, // Prefix Opcode 0: Write Enable + SF_INST_WREN // Prefix Opcode 1: Write Enable (this part doesn't support EWSR) + }, + { + {EnumSpiOpcodeReadNoAddr, SF_INST_JEDEC_READ_ID, EnumSpiCycle50MHz, EnumSpiOperationJedecId }, // Opcode 0: Read ID + {EnumSpiOpcodeRead, SF_INST_READ, EnumSpiCycle50MHz, EnumSpiOperationReadData }, // Opcode 1: Read + {EnumSpiOpcodeReadNoAddr, SF_INST_RDSR, EnumSpiCycle50MHz, EnumSpiOperationReadStatus }, // Opcode 2: Read Status Register + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRDI, EnumSpiCycle50MHz, EnumSpiOperationWriteDisable }, // Opcode 3: Write Disable + {EnumSpiOpcodeWrite, SF_INST_SERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_4K_Byte }, // Opcode 4: Sector Erase (4KB) + {EnumSpiOpcodeWrite, SF_INST_64KB_ERASE, EnumSpiCycle50MHz, EnumSpiOperationErase_64K_Byte }, // Opcode 5: Block Erase (64KB + {EnumSpiOpcodeWrite, SF_INST_PROG, EnumSpiCycle50MHz, EnumSpiOperationProgramData_1_Byte}, // Opcode 6: Byte Program + {EnumSpiOpcodeWriteNoAddr, SF_INST_WRSR, EnumSpiCycle50MHz, EnumSpiOperationWriteStatus }, // Opcode 7: Write Status Register + }, + + // + // The offset of the start of the BIOS image in flash. This value is platform specific + // and depends on the system flash map. If BIOS size is bigger than flash return -1. + // + ((AMIC_A25L16_SIZE >= FLASH_SIZE) ? AMIC_A25L16_SIZE - FLASH_SIZE : (UINTN) (-1)), + + // + // The size of the BIOS image in flash. This value is platform specific and depends on the system flash map. + // + FLASH_SIZE + } +}; diff --git a/Vlv2TbltDevicePkg/Library/I2CLib/I2CLib.c b/Vlv2TbltDevicePkg/Library/I2CLib/I2CLib.c new file mode 100644 index 0000000000..3e653816ac --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/I2CLib/I2CLib.c @@ -0,0 +1,51 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + I2CLib.c + + + +--*/ +#ifdef ECP_FLAG +#include "EdkIIGlueDxe.h" +#else +#include +#include +#endif +#include +#include +#include +#include +#ifdef ECP_FLAG +#include "I2CLib.h" +#else +#include +#endif +#include +#ifndef ECP_FLAG +#include +#endif + +EFI_STATUS ByteReadI2C( + IN UINT8 BusNo, + IN UINT8 SlaveAddress, + IN UINT8 Offset, + IN UINTN ReadBytes, + OUT UINT8 *ReadBuffer + ) +{ + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/Library/I2CLib/I2CLibNull.inf b/Vlv2TbltDevicePkg/Library/I2CLib/I2CLibNull.inf new file mode 100644 index 0000000000..487982c155 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/I2CLib/I2CLibNull.inf @@ -0,0 +1,53 @@ +## @file +# Null instance of Debug Agent Library with empty functions. +# +# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = I2CLib + FILE_GUID = 7f62bf44-2ba7-4c2d-9d4a-91c8906ff053 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = I2CLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + I2CLib.c + +[LibraryClasses] + BaseLib + IoLib + TimerLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + +[Protocols] + gEfiGlobalNvsAreaProtocolGuid diff --git a/Vlv2TbltDevicePkg/Library/IntelPchAcpiTimerLib/CommonHeader.h b/Vlv2TbltDevicePkg/Library/IntelPchAcpiTimerLib/CommonHeader.h new file mode 100644 index 0000000000..213940e231 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/IntelPchAcpiTimerLib/CommonHeader.h @@ -0,0 +1,32 @@ +/**@file + Common header file shared by all source files. + + This file includes package header files, library classes and protocol, PPI & GUID definitions. + + Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + +#include +#include + +#include +#include +#include +#include +#include + +#endif diff --git a/Vlv2TbltDevicePkg/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.c b/Vlv2TbltDevicePkg/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.c new file mode 100644 index 0000000000..09c42a4914 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.c @@ -0,0 +1,260 @@ +/** @file + ICH9 ACPI Timer implements one instance of Timer Library. + +Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include "CommonHeader.h" + +/** + 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 +IntelPchAcpiTimerLibConstructor ( + VOID + ) +{ + if ((PchLpcPciCfg8(R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_EN) == 0) { + // + // If ACPI I/O space is not enabled, program ACPI I/O base address and enable it. + // + MmioWrite16 ( + MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_BASE + ), + ((PcdGet16 (PcdPchAcpiIoPortBaseAddress) & B_PCH_LPC_ACPI_BASE_BAR) | B_PCH_LPC_ACPI_BASE_EN) + ); + } + 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 (PcdPchAcpiIoPortBaseAddress) + R_PCH_ACPI_PM1_TMR); +} + +/** + 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_PCH_ACPI_PM1_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_PCH_ACPI_PM1_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 (UINT64)InternalAcpiGetTimerTick (); +} + +/** + 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_PCH_ACPI_PM1_TMR_MAX_VAL - 1; + } + + return V_PCH_ACPI_PM1_TMR_FREQUENCY; +} + +/** + 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 NanoSeconds; + UINT32 Remainder; + + // + // Ticks + // Time = --------- x 1,000,000,000 + // Frequency + // + NanoSeconds = MultU64x32 (DivU64x32Remainder (Ticks, V_PCH_ACPI_PM1_TMR_FREQUENCY, &Remainder), 1000000000u); + + // + // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000) + // will not overflow 64-bit. + // + NanoSeconds += DivU64x32 (MultU64x32 ((UINT64) Remainder, 1000000000u), V_PCH_ACPI_PM1_TMR_FREQUENCY); + + return NanoSeconds; +} + + diff --git a/Vlv2TbltDevicePkg/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf b/Vlv2TbltDevicePkg/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf new file mode 100644 index 0000000000..f4fb5abc2c --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf @@ -0,0 +1,56 @@ +#/** @file +# Intel ICH9 Acpi Timer Instance +# +# ICH9 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) 2007 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = IntelPchAcpiTimerLib + FILE_GUID = 0C0AC8C1-E368-4d20-85FE-23EFB3DB094E + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + CONSTRUCTOR = IntelPchAcpiTimerLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + IntelPchAcpiTimerLib.c + CommonHeader.h + +[Packages] + MdePkg/MdePkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + +[LibraryClasses] + PcdLib + PciLib + IoLib + BaseLib + +[Pcd.common] + gEfiPchTokenSpaceGuid.PcdPchAcpiIoPortBaseAddress + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.c b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.c new file mode 100644 index 0000000000..1fc731205b --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.c @@ -0,0 +1,426 @@ +/** @file + Clock generator setting for multiplatform. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include +#include +#include +#include + +#ifndef __GNUC__ +#pragma optimize( "", off ) +#endif + +#define CLKGEN_EN 1 +#define EFI_DEBUG 1 + +CLOCK_GENERATOR_DETAILS mSupportedClockGeneratorTable[] = +{ + { ClockGeneratorCk410, CK410_GENERATOR_ID , CK410_GENERATOR_SPREAD_SPECTRUM_BYTE, CK410_GENERATOR_SPREAD_SPECTRUM_BIT }, + { ClockGeneratorCk505, CK505_GENERATOR_ID , CK505_GENERATOR_SPREAD_SPECTRUM_BYTE, CK505_GENERATOR_SPREAD_SPECTRUM_BIT } +}; + +/** + Configure the clock generator using the SMBUS PPI services. + + This function performs a block write, and dumps debug information. + + @param PeiServices General purpose services available to every PEIM. + @param ClockType Clock generator's model name. + @param ClockAddress SMBUS address of clock generator. + @param ConfigurationTableLength Length of configuration table. + @param ConfigurationTable Pointer of configuration table. + + @retval EFI_SUCCESS - Operation success. + +**/ +EFI_STATUS +ConfigureClockGenerator ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_SMBUS_PPI *SmbusPpi, + IN CLOCK_GENERATOR_TYPE ClockType, + IN UINT8 ClockAddress, + IN UINTN ConfigurationTableLength, + IN OUT UINT8 *ConfigurationTable + ) +{ + + EFI_STATUS Status; + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + UINT8 Buffer[MAX_CLOCK_GENERATOR_BUFFER_LENGTH]; + UINTN Length; + EFI_SMBUS_DEVICE_COMMAND Command; +#if CLKGEN_CONFIG_EXTRA + UINT8 j; +#endif + + // + // Verify input arguments + // + ASSERT_EFI_ERROR (ConfigurationTableLength >= 6); + ASSERT_EFI_ERROR (ConfigurationTableLength <= MAX_CLOCK_GENERATOR_BUFFER_LENGTH); + ASSERT_EFI_ERROR (ClockType < ClockGeneratorMax); + ASSERT_EFI_ERROR (ConfigurationTable != NULL); + + // + // Read the clock generator + // + SlaveAddress.SmbusDeviceAddress = ClockAddress >> 1; + Length = sizeof (Buffer); + Command = 0; + Status = SmbusPpi->Execute ( + PeiServices, + SmbusPpi, + SlaveAddress, + Command, + EfiSmbusReadBlock, + FALSE, + &Length, + Buffer + ); + ASSERT_EFI_ERROR (Status); + +#ifdef EFI_DEBUG + { + UINT8 i; + for (i = 0; i < sizeof (Buffer); i++) { + DEBUG((EFI_D_ERROR, "CK505 default Clock Generator Byte %d: %x\n", i, Buffer[i])); + } +#if CLKGEN_EN + for (i = 0; i < ConfigurationTableLength; i++) { + DEBUG((EFI_D_ERROR, "BIOS structure Clock Generator Byte %d: %x\n", i, ConfigurationTable[i])); + } +#endif + } +#endif + + DEBUG((EFI_D_ERROR, "Expected Clock Generator ID is %x, expecting %x\n", mSupportedClockGeneratorTable[ClockType].ClockId,(Buffer[7]&0xF))); + + // + // Program clock generator + // + Command = 0; +#if CLKGEN_EN +#if CLKGEN_CONFIG_EXTRA + for (j = 0; j < ConfigurationTableLength; j++) { + Buffer[j] = ConfigurationTable[j]; + } + + Buffer[30] = 0x00; + + Status = SmbusPpi->Execute ( + PeiServices, + SmbusPpi, + SlaveAddress, + Command, + EfiSmbusWriteBlock, + FALSE, + &Length, + Buffer + ); +#else + Status = SmbusPpi->Execute ( + PeiServices, + SmbusPpi, + SlaveAddress, + Command, + EfiSmbusWriteBlock, + FALSE, + &ConfigurationTableLength, + ConfigurationTable + ); +#endif // CLKGEN_CONFIG_EXTRA +#else + ConfigurationTable[4] = (ConfigurationTable[4] & 0x3) | (Buffer[4] & 0xFC); + Command = 4; + Length = 1; + Status = SmbusPpi->Execute ( + PeiServices, + SmbusPpi, + SlaveAddress, + Command, + EfiSmbusWriteBlock, + FALSE, + &Length, + &ConfigurationTable[4] + ); +#endif //CLKGEN_EN + ASSERT_EFI_ERROR (Status); + + // + // Dump contents after write + // + #ifdef EFI_DEBUG + { + UINT8 i; + SlaveAddress.SmbusDeviceAddress = ClockAddress >> 1; + Length = sizeof (Buffer); + Command = 0; + Status = SmbusPpi->Execute ( + PeiServices, + SmbusPpi, + SlaveAddress, + Command, + EfiSmbusReadBlock, + FALSE, + &Length, + Buffer + ); + + for (i = 0; i < ConfigurationTableLength; i++) { + DEBUG((EFI_D_ERROR, "Clock Generator Byte %d: %x\n", i, Buffer[i])); + } + } + #endif + + return EFI_SUCCESS; +} + +/** + Configure the clock generator using the SMBUS PPI services. + + This function performs a block write, and dumps debug information. + + @param PeiServices General purpose services available to every PEIM. + @param ClockType Clock generator's model name. + @param ClockAddress SMBUS address of clock generator. + @param ConfigurationTableLength Length of configuration table. + @param ConfigurationTable Pointer of configuration table. + + + @retval EFI_SUCCESS Operation success. + +**/ +UINT8 +ReadClockGeneratorID ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_SMBUS_PPI *SmbusPpi, + IN UINT8 ClockAddress + ) +{ + EFI_STATUS Status; + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + UINT8 Buffer[MAX_CLOCK_GENERATOR_BUFFER_LENGTH]; + UINTN Length; + EFI_SMBUS_DEVICE_COMMAND Command; + + // + // Read the clock generator + // + SlaveAddress.SmbusDeviceAddress = ClockAddress >> 1; + Length = sizeof (Buffer); + Command = 0; + Status = SmbusPpi->Execute ( + PeiServices, + SmbusPpi, + SlaveAddress, + Command, + EfiSmbusReadBlock, + FALSE, + &Length, + Buffer + ); + + // + // Sanity check that the requested clock type is present in our supported clocks table + // + DEBUG((EFI_D_ERROR, "Expected Clock Generator ID is 0x%x\n", Buffer[7])); + + return (Buffer[7]); +} + +/** + Configure the clock generator to enable free-running operation. This keeps + the clocks from being stopped when the system enters C3 or C4. + + @param None + + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +ConfigurePlatformClocks ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *SmbusPpi + ) +{ + // + // Comment it out for now + // Not supported by Hybrid model. + // + EFI_STATUS Status; + UINT8 *ConfigurationTable; + + CLOCK_GENERATOR_TYPE ClockType = ClockGeneratorCk505; + UINT8 ConfigurationTable_Desktop[] = CLOCK_GENERATOR_SETTINGS_DESKTOP; + UINT8 ConfigurationTable_Mobile[] = CLOCK_GENERATOR_SETTINGS_MOBILE; + UINT8 ConfigurationTable_Tablet[] = CLOCK_GENERATOR_SEETINGS_TABLET; + + EFI_PLATFORM_INFO_HOB *PlatformInfoHob; + BOOLEAN EnableSpreadSpectrum; + UINT8 ClockGenID=0; + SYSTEM_CONFIGURATION SystemConfiguration; + + UINTN Length; + EFI_SMBUS_DEVICE_COMMAND Command; + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + UINT8 Data; + + UINT8 ClockAddress = CLOCK_GENERATOR_ADDRESS; + UINTN VariableSize; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; + + // + // Obtain Platform Info from HOB. + // + Status = GetPlatformInfoHob ((CONST EFI_PEI_SERVICES **) PeiServices, &PlatformInfoHob); + ASSERT_EFI_ERROR (Status); + + DEBUG((EFI_D_ERROR, "PlatformInfo protocol is working in ConfigurePlatformClocks()...%x\n",PlatformInfoHob->PlatformFlavor)); + + // + // Locate SMBUS PPI + // + Status = (**PeiServices).LocatePpi ( + (CONST EFI_PEI_SERVICES **) PeiServices, + &gEfiPeiSmbusPpiGuid, + 0, + NULL, + &SmbusPpi + ); + ASSERT_EFI_ERROR (Status); + + Data = 0; + SlaveAddress.SmbusDeviceAddress = ClockAddress >> 1; + Length = 1; + Command = 0x87; //Control Register 7 Vendor ID Check + Status = ((EFI_PEI_SMBUS_PPI *) SmbusPpi)->Execute ( + PeiServices, + SmbusPpi, + SlaveAddress, + Command, + EfiSmbusReadByte, + FALSE, + &Length, + &Data + ); + + if (EFI_ERROR (Status) || ((Data & 0x0F) != CK505_GENERATOR_ID)) { + DEBUG((EFI_D_ERROR, "Clock Generator CK505 Not Present, vendor ID on board is %x\n",(Data & 0x0F))); + return EFI_SUCCESS; +} + ClockGenID = Data & 0x0F; + + EnableSpreadSpectrum = FALSE; + VariableSize = sizeof (SYSTEM_CONFIGURATION); + ZeroMem (&SystemConfiguration, sizeof (SYSTEM_CONFIGURATION)); + + Status = (*PeiServices)->LocatePpi ( + (CONST EFI_PEI_SERVICES **) PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (VOID **) &Variable + ); + // + // Use normal setup default from NVRAM variable, + // the Platform Mode (manufacturing/safe/normal) is handle in PeiGetVariable. + // + VariableSize = sizeof(SYSTEM_CONFIGURATION); + Status = Variable->GetVariable (Variable, + L"Setup", + &gEfiSetupVariableGuid, + NULL, + &VariableSize, + &SystemConfiguration); + + if(!EFI_ERROR (Status)){ + EnableSpreadSpectrum = SystemConfiguration.EnableClockSpreadSpec; + } + + // + // Perform platform-specific intialization dependent upon Board ID: + // + DEBUG((EFI_D_ERROR, "board id is %x, platform id is %x\n",PlatformInfoHob->BoardId,PlatformInfoHob->PlatformFlavor)); + + + switch (PlatformInfoHob->BoardId) { + case BOARD_ID_MINNOW2: + default: + switch(PlatformInfoHob->PlatformFlavor) { + case FlavorTablet: + ConfigurationTable = ConfigurationTable_Tablet; + Length = sizeof (ConfigurationTable_Tablet); + break; + case FlavorMobile: + ConfigurationTable = ConfigurationTable_Mobile; + Length = sizeof (ConfigurationTable_Mobile); + break; + case FlavorDesktop: + default: + ConfigurationTable = ConfigurationTable_Desktop; + Length = sizeof (ConfigurationTable_Desktop); + break; + } + break; + } + + // + // Perform common clock initialization: + // + // Program Spread Spectrum function. + // + if (EnableSpreadSpectrum) + { + ConfigurationTable[mSupportedClockGeneratorTable[ClockType].SpreadSpectrumByteOffset] |= mSupportedClockGeneratorTable[ClockType].SpreadSpectrumBitOffset; + } else { + ConfigurationTable[mSupportedClockGeneratorTable[ClockType].SpreadSpectrumByteOffset] &= ~(mSupportedClockGeneratorTable[ClockType].SpreadSpectrumBitOffset); + } + + +#if CLKGEN_EN + Status = ConfigureClockGenerator (PeiServices, SmbusPpi, ClockType, ClockAddress, Length, ConfigurationTable); + ASSERT_EFI_ERROR (Status); +#endif // CLKGEN_EN + return EFI_SUCCESS; +} + +static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiSmbusPpiGuid, + ConfigurePlatformClocks + } +}; + +EFI_STATUS +InstallPlatformClocksNotify ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + DEBUG ((EFI_D_INFO, "InstallPlatformClocksNotify()...\n")); + + Status = (*PeiServices)->NotifyPpi(PeiServices, &mNotifyList[0]); + ASSERT_EFI_ERROR (Status); + return EFI_SUCCESS; + +} + +#ifndef __GNUC__ +#pragma optimize( "", on ) +#endif diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.h b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.h new file mode 100644 index 0000000000..4ec5b881ab --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardClkGens/BoardClkGens.h @@ -0,0 +1,260 @@ +/**@file + Clock generator setting for multiplatform. + + This file includes package header files, library classes. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _BOARD_CLK_GEN_H_ +#define _BOARD_CLK_GEN_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define CLOCK_GENERATOR_ADDRESS 0xd2 + +#define CLOCK_GENERATOR_SEETINGS_TABLET {0xB1, 0x82, 0xFF, 0xBF, 0xFF, 0x80} +#define CLOCK_GENERATOR_SETTINGS_MOBILE {0xB1, 0x82, 0xFF, 0xBF, 0xFF, 0x80} +#define CLOCK_GENERATOR_SETTINGS_DESKTOP {0xB1, 0x82, 0xFF, 0xBF, 0xFF, 0x80} + +typedef enum { + ClockGeneratorCk410, + ClockGeneratorCk505, + ClockGeneratorMax +} CLOCK_GENERATOR_TYPE; + +typedef struct { + CLOCK_GENERATOR_TYPE ClockType; + UINT8 ClockId; + UINT8 SpreadSpectrumByteOffset; + UINT8 SpreadSpectrumBitOffset; +} CLOCK_GENERATOR_DETAILS; + +#define MAX_CLOCK_GENERATOR_BUFFER_LENGTH 0x20 + +// +// CK410 Definitions +// +#define CK410_GENERATOR_ID 0x65 +#define CK410_GENERATOR_SPREAD_SPECTRUM_BYTE 1 +#define CK410_GENERATOR_SPREAD_SPECTRUM_BIT BIT0 +#define CK410_GENERATOR_CLOCK_FREERUN_BYTE 4 +#define CK410_GENERATOR_CLOCK_FREERUN_BIT (BIT0 | BIT1 | BIT2) + +// +// CK505 Definitions +// +#define VF_CK505_GENERATOR_ID 0x5 +#define CK505_GENERATOR_ID 0x5 // Confirmed readout is 5 +#define CK505_GENERATOR_SPREAD_SPECTRUM_BYTE 4 +#define CK505_GENERATOR_SPREAD_SPECTRUM_BIT (BIT0 | BIT1) +#define CK505_GENERATOR_PERCENT_SPREAD_BYTE 1 +#define CK505_GENERATOR_PERCENT_MASK ~(0xE) +#define CK505_GENERATOR_PERCENT_250_VALUE 0xC +#define CK505_GENERATOR_PERCENT_050_VALUE 0x4 +#define CK505_GENERATOR_PERCENT_000_VALUE 0x2 + +// +// IDT Definitions +// +#define IDT_GENERATOR_ID_REVA 0x1 //IDT Rev A +#define IDTRevA_GENERATOR_SPREAD_SPECTRUM_BYTE 0 +#define IDTRevA_GENERATOR_SPREAD_SPECTRUM_BIT BIT0 +#define IDTRevA_GENERATOR_PERCENT_SPREAD_BYTE 5 +#define IDTRevA_GENERATOR_PERCENT_250_VALUE 0xF +#define IDTRevA_GENERATOR_PERCENT_050_VALUE 0x3 +#define IDTRevA_GENERATOR_PERCENT_000_VALUE 0xE +#define IDTRevA_GENERATOR_PERCENT_MASK ~(0xF) + +#define IDT_GENERATOR_ID_REVB 0x11 //IDT RevB +#define IDT_GENERATOR_ID_REVD 0x21 //IDT RevD + +// +// CLOCK CONTROLLER +// SmBus address to read DIMM SPD +// +#define SMBUS_BASE_ADDRESS 0xEFA0 +#define SMBUS_BUS_DEV_FUNC 0x1F0300 +#define PLATFORM_NUM_SMBUS_RSVD_ADDRESSES 4 +#define SMBUS_ADDR_CH_A_1 0xA0 +#define SMBUS_ADDR_CH_A_2 0xA2 +#define SMBUS_ADDR_CH_B_1 0xA4 +#define SMBUS_ADDR_CH_B_2 0xA6 + +// +// Bits for FWH_DEC_EN1—Firmware Hub Decode Enable Register (LPC I/F—D31:F0) +// +#define B_ICH_LPC_FWH_BIOS_DEC_F0 0x4000 +#define B_ICH_LPC_FWH_BIOS_DEC_E0 0x1000 +#define B_ICH_LPC_FWH_BIOS_DEC_E8 0x2000 +#define B_ICH_LPC_FWH_BIOS_LEG_F 0x0080 +#define B_ICH_LPC_FWH_BIOS_LEG_E 0x0040 + + +// +// An arbitrary maximum length for clock generator buffers +// +#define MAX_CLOCK_GENERATOR_BUFFER_LENGTH 0x20 + +// +// SmBus Bus Device Function and Register Definitions +// +#define SMBUS_BUS_NUM 0 +#define SMBUS_DEV_NUM 31 +#define SMBUS_FUNC_NUM 3 +#define SMBUS_BUS_DEV_FUNC_NUM \ + SB_PCI_CFG_ADDRESS(SMBUS_BUS_NUM, SMBUS_DEV_NUM, SMBUS_FUNC_NUM, 0) + +// +//ICH7: SMBus I/O Space Equates; +// +#define BIT_SLAVE_ADDR BIT00 +#define BIT_COMMAND BIT01 +#define BIT_DATA BIT02 +#define BIT_COUNT BIT03 +#define BIT_WORD BIT04 +#define BIT_CONTROL BIT05 +#define BIT_PEC BIT06 +#define BIT_READ BIT07 +#define SMBUS_IO_READ_BIT BIT00 + + +#define SMB_CMD_QUICK 0x00 +#define SMB_CMD_BYTE 0x04 +#define SMB_CMD_BYTE_DATA 0x08 +#define SMB_CMD_WORD_DATA 0x0C +#define SMB_CMD_PROCESS_CALL 0x10 +#define SMB_CMD_BLOCK 0x14 +#define SMB_CMD_I2C_READ 0x18 +#define SMB_CMD_RESERVED 0x1c + +#define HST_STS_BYTE_DONE 0x80 +#define SMB_HST_STS 0x000 +#define SMB_HST_CNT 0x002 +#define SMB_HST_CMD 0x003 +#define SMB_HST_ADD 0x004 +#define SMB_HST_DAT_0 0x005 +#define SMB_HST_DAT_1 0x006 +#define SMB_HST_BLK_DAT 0x007 +#define SMB_PEC 0x008 +#define SMB_RCV_SLVA 0x009 +#define SMB_SLV_DAT 0x00A +#define SMB_AUX_STS 0x00C +#define SMB_AUX_CTL 0x00D +#define SMB_SMLINK_PIN_CTL 0x00E +#define SMB_SMBUS_PIN_CTL 0x00F +#define SMB_SLV_STS 0x010 +#define SMB_SLV_CMD 0x011 +#define SMB_NTFY_DADDR 0x014 +#define SMB_NTFY_DLOW 0x016 +#define SMB_NTFY_DHIGH 0x017 + +// +// PCI Register Definitions - use SmbusPolicyPpi->PciAddress + offset listed below +// +#define R_COMMAND 0x04 // PCI Command Register, 16bit +#define B_IOSE 0x01 // RW +#define R_BASE_ADDRESS 0x20 // PCI BAR for SMBus I/O +#define B_BASE_ADDRESS 0xFFE0 // RW +#define R_HOST_CONFIGURATION 0x40 // SMBus Host Configuration Register +#define B_HST_EN 0x01 // RW +#define B_SMB_SMI_EN 0x02 // RW +#define B_I2C_EN 0x04 // RW +// +// I/O Register Definitions - use SmbusPolicyPpi->BaseAddress + offset listed below +// +#define HOST_STATUS_REGISTER 0x00 // Host Status Register R/W +#define HST_STS_HOST_BUSY 0x01 // RO +#define HST_STS_INTR 0x02 // R/WC +#define HST_STS_DEV_ERR 0x04 // R/WC +#define HST_STS_BUS_ERR 0x08 // R/WC +#define HST_STS_FAILED 0x10 // R/WC +#define SMBUS_B_SMBALERT_STS 0x20 // R/WC +#define HST_STS_INUSE 0x40 // R/WC +#define SMBUS_B_BYTE_DONE_STS 0x80 // R/WC +#define SMBUS_B_HSTS_ALL 0xFF // R/WC +#define HOST_CONTROL_REGISTER 0x02 // Host Control Register R/W +#define HST_CNT_INTREN 0x01 // RW +#define HST_CNT_KILL 0x02 // RW +#define SMBUS_B_SMB_CMD 0x1C // RW +#define SMBUS_V_SMB_CMD_QUICK 0x00 +#define SMBUS_V_SMB_CMD_BYTE 0x04 +#define SMBUS_V_SMB_CMD_BYTE_DATA 0x08 +#define SMBUS_V_SMB_CMD_WORD_DATA 0x0C +#define SMBUS_V_SMB_CMD_PROCESS_CALL 0x10 +#define SMBUS_V_SMB_CMD_BLOCK 0x14 +#define SMBUS_V_SMB_CMD_IIC_READ 0x18 +#define SMBUS_B_LAST_BYTE 0x20 // WO +#define HST_CNT_START 0x40 // WO +#define HST_CNT_PEC_EN 0x80 // RW +#define HOST_COMMAND_REGISTER 0x03 // Host Command Register R/W +#define XMIT_SLAVE_ADDRESS_REGISTER 0x04 // Transmit Slave Address Register R/W +#define SMBUS_B_RW_SEL 0x01 // RW +#define SMBUS_B_ADDRESS 0xFE // RW +#define HOST_DATA_0_REGISTER 0x05 // Data 0 Register R/W +#define HOST_DATA_1_REGISTER 0x06 // Data 1 Register R/W +#define HOST_BLOCK_DATA_BYTE_REGISTER 0x07 // Host Block Data Register R/W +#define SMBUS_R_PEC 0x08 // Packet Error Check Data Register R/W +#define SMBUS_R_RSA 0x09 // Receive Slave Address Register R/W +#define SMBUS_B_SLAVE_ADDR 0x7F // RW +#define SMBUS_R_SD 0x0A // Receive Slave Data Register R/W +#define SMBUS_R_AUXS 0x0C // Auxiliary Status Register R/WC +#define SMBUS_B_CRCE 0x01 //R/WC +#define AUXILIARY_CONTROL_REGISTER 0x0D // Auxiliary Control Register R/W +#define SMBUS_B_AAC 0x01 //R/W +#define SMBUS_B_E32B 0x02 //R/W +#define SMBUS_R_SMLC 0x0E // SMLINK Pin Control Register R/W +#define SMBUS_B_SMLINK0_CUR_STS 0x01 // RO +#define SMBUS_B_SMLINK1_CUR_STS 0x02 // RO +#define SMBUS_B_SMLINK_CLK_CTL 0x04 // RW +#define SMBUS_R_SMBC 0x0F // SMBus Pin Control Register R/W +#define SMBUS_B_SMBCLK_CUR_STS 0x01 // RO +#define SMBUS_B_SMBDATA_CUR_STS 0x02 // RO +#define SMBUS_B_SMBCLK_CTL 0x04 // RW +#define SMBUS_R_SSTS 0x10 // Slave Status Register R/WC +#define SMBUS_B_HOST_NOTIFY_STS 0x01 // R/WC +#define SMBUS_R_SCMD 0x11 // Slave Command Register R/W +#define SMBUS_B_HOST_NOTIFY_INTREN 0x01 // R/W +#define SMBUS_B_HOST_NOTIFY_WKEN 0x02 // R/W +#define SMBUS_B_SMBALERT_DIS 0x04 // R/W +#define SMBUS_R_NDA 0x14 // Notify Device Address Register RO +#define SMBUS_B_DEVICE_ADDRESS 0xFE // RO +#define SMBUS_R_NDLB 0x16 // Notify Data Low Byte Register RO +#define SMBUS_R_NDHB 0x17 // Notify Data High Byte Register RO +#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 + + +EFI_STATUS +ConfigurePlatformClocks ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *SmbusPpi + ); + + +#endif diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardGpios/BoardGpios.c b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardGpios/BoardGpios.c new file mode 100644 index 0000000000..092d3f3783 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardGpios/BoardGpios.c @@ -0,0 +1,535 @@ +/** @file + Gpio setting for multiplatform.. + + Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include +#include + +// +//AlpineValley platform ocde begin +// +#define AV_SC_REG_GPIOS_MUXES_SEL0 0x48 +#define AV_SC_REG_GPIOS_MUXES_SEL1 0x4C +#define AV_SC_REG_GPIOS_MUXES_SEL2 0x50 +#define AV_SC_REG_GPIOS_MUXES_EN0 0x54 +#define AV_SC_REG_GPIOS_MUXES_EN1 0x58 +#define AV_SC_REG_GPIOS_MUXES_EN2 0x5C +// +//AlpineValley platform code end +// + +EFI_GUID gPeiSmbusPpiGuid = EFI_PEI_SMBUS_PPI_GUID; + +/** + @param None + + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +ConfigurePlatformSysCtrlGpio ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *SmbusPpi + ) +{ + // + //AlpineValley platform code begin + // + // Initialize GPIO Settings: + // + UINT32 Status; + EFI_PLATFORM_INFO_HOB *PlatformInfoHob; + + DEBUG ((EFI_D_INFO, "ConfigurePlatformSysCtrlGpio()...\n")); + + // + // Obtain Platform Info from HOB. + // + Status = GetPlatformInfoHob ((const EFI_PEI_SERVICES **)PeiServices, &PlatformInfoHob); + ASSERT_EFI_ERROR (Status); + + // + // The GPIO settings are dependent upon the platform. Obtain the Board ID through + // the EC to determine the current platform. + // + DEBUG ((EFI_D_INFO, "Platform Flavor | Board ID = 0x%X | 0x%X\n", PlatformInfoHob->PlatformFlavor, PlatformInfoHob->BoardId)); + + + + Status = (**PeiServices).LocatePpi ( + (const EFI_PEI_SERVICES **)PeiServices, + &gPeiSmbusPpiGuid, + 0, + NULL, + (void **)&SmbusPpi + ); + ASSERT_EFI_ERROR (Status); + + // + // Select/modify the GPIO initialization data based on the Board ID. + // + switch (PlatformInfoHob->BoardId) + { + default: + Status = EFI_SUCCESS; + + // + // Do nothing for other RVP boards. + // + break; + } + return Status; +} + +static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiSmbusPpiGuid, + ConfigurePlatformSysCtrlGpio + } +}; + +EFI_STATUS +InstallPlatformSysCtrlGPIONotify ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + DEBUG ((EFI_D_INFO, "InstallPlatformSysCtrlGPIONotify()...\n")); + + Status = (*PeiServices)->NotifyPpi(PeiServices, &mNotifyList[0]); + ASSERT_EFI_ERROR (Status); + return EFI_SUCCESS; + +} + +#define V_PCH_ILB_IRQE_UARTIRQEN_IRQ3 BIT3 // UART IRQ3 Enable + +/** + Returns the Correct GPIO table for Mobile/Desktop respectively. + Before call it, make sure PlatformInfoHob->BoardId&PlatformFlavor is get correctly. + + @param PeiServices General purpose services available to every PEIM. + @param PlatformInfoHob PlatformInfoHob pointer with PlatformFlavor specified. + @param BoardId BoardId ID as determined through the EC. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_DEVICE_ERROR KSC fails to respond. + +**/ +EFI_STATUS +MultiPlatformGpioTableInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ) +{ + EFI_STATUS Status; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiReadOnlyVarPpi; + UINTN VarSize; + SYSTEM_CONFIGURATION SystemConfiguration; + + DEBUG ((EFI_D_INFO, "MultiPlatformGpioTableInit()...\n")); + + // + // Select/modify the GPIO initialization data based on the Board ID. + // + switch (PlatformInfoHob->BoardId) { + + case BOARD_ID_MINNOW2: // Minnow2 + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&PeiReadOnlyVarPpi + ); + ASSERT_EFI_ERROR (Status); + + VarSize = sizeof (SYSTEM_CONFIGURATION); + Status = PeiReadOnlyVarPpi->GetVariable ( + PeiReadOnlyVarPpi, + PLATFORM_SETUP_VARIABLE_NAME, + &gEfiSetupVariableGuid, + NULL, + &VarSize, + &SystemConfiguration + ); + + if (SystemConfiguration.GpioWakeCapability == 1) { + PlatformInfoHob->PlatformCfioData = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2CfioInitData2; + } + else { + PlatformInfoHob->PlatformCfioData = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2CfioInitData; + } + + PlatformInfoHob->PlatformGpioData_NC = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2_GpioInitData_NC[0]; + PlatformInfoHob->PlatformGpioData_SC = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2_GpioInitData_SC[0]; + PlatformInfoHob->PlatformGpioData_SUS = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2_GpioInitData_SUS[0]; + break; + + } + + return EFI_SUCCESS; +} + +UINT32 +GPIORead32 ( + IN UINT32 mmio_conf + ) +{ + UINT32 conf_val; + UINT32 i; + conf_val = MmioRead32(mmio_conf); + for(i=0;i<5;i++){ + if(conf_val == 0xffffffff) + conf_val = MmioRead32(mmio_conf); + else + break; + } + + return conf_val; +} + +/** + + Set GPIO CONF0 and PAD_VAL registers for NC/SC/SUS GPIO clusters + + @param Gpio_Mmio_Offset GPIO_SCORE_OFFSET or GPIO_NCORE_OFFSET or GPIO_SSUS_OFFSET. + @param Gpio_Pin_Num Pin numbers to config for each GPIO clusters. + @param Gpio_Conf_Data GPIO_CONF_PAD_INIT data array for each GPIO clusters. + +**/ +VOID +InternalGpioConfig ( + IN UINT32 Gpio_Mmio_Offset, + IN UINT32 Gpio_Pin_Num, + GPIO_CONF_PAD_INIT* Gpio_Conf_Data + ) +{ + UINT32 index; + UINT32 mmio_conf0; + UINT32 mmio_padval; + PAD_CONF0 conf0_val; + PAD_VAL pad_val; + + // + // GPIO WELL -- Memory base registers + // + + // A0 BIOS Spec doesn't mention it although X0 does. comment out now. + // GPIO write 0x01001002 to IOBASE + Gpio_Mmio_Offset + 0x0900 + // + for(index=0; index < Gpio_Pin_Num; index++) + { + // + // Calculate the MMIO Address for specific GPIO pin CONF0 register pointed by index. + // + mmio_conf0 = IO_BASE_ADDRESS + Gpio_Mmio_Offset + R_PCH_CFIO_PAD_CONF0 + Gpio_Conf_Data[index].offset * 16; + mmio_padval= IO_BASE_ADDRESS + Gpio_Mmio_Offset + R_PCH_CFIO_PAD_VAL + Gpio_Conf_Data[index].offset * 16; + +#ifdef EFI_DEBUG + DEBUG ((EFI_D_INFO, "%s, ", Gpio_Conf_Data[index].pad_name)); + +#endif + DEBUG ((EFI_D_INFO, "Usage = %d, Func# = %d, IntType = %d, Pull Up/Down = %d, MMIO Base = 0x%08x, ", + Gpio_Conf_Data[index].usage, + Gpio_Conf_Data[index].func, + Gpio_Conf_Data[index].int_type, + Gpio_Conf_Data[index].pull, + mmio_conf0)); + + // + // Step 1: PadVal Programming. + // + pad_val.dw = GPIORead32(mmio_padval); + + // + // Config PAD_VAL only for GPIO (Non-Native) Pin + // + if(Native != Gpio_Conf_Data[index].usage) + { + pad_val.dw &= ~0x6; // Clear bits 1:2 + pad_val.dw |= (Gpio_Conf_Data[index].usage & 0x6); // Set bits 1:2 according to PadVal + + // + // set GPO default value + // + if(Gpio_Conf_Data[index].usage == GPO && Gpio_Conf_Data[index].gpod4 != NA) + { + pad_val.r.pad_val = Gpio_Conf_Data[index].gpod4; + } + } + + + DEBUG ((EFI_D_INFO, "Set PAD_VAL = 0x%08x, ", pad_val.dw)); + + MmioWrite32(mmio_padval, pad_val.dw); + + // + // Step 2: CONF0 Programming + // Read GPIO default CONF0 value, which is assumed to be default value after reset. + // + conf0_val.dw = GPIORead32(mmio_conf0); + + // + // Set Function # + // + conf0_val.r.Func_Pin_Mux = Gpio_Conf_Data[index].func; + + if(GPO == Gpio_Conf_Data[index].usage) + { + // + // If used as GPO, then internal pull need to be disabled. + // + conf0_val.r.Pull_assign = 0; // Non-pull + } + else + { + // + // Set PullUp / PullDown + // + if(P_20K_H == Gpio_Conf_Data[index].pull) + { + conf0_val.r.Pull_assign = 0x1; // PullUp + conf0_val.r.Pull_strength = 0x2;// 20K + } + else if(P_20K_L == Gpio_Conf_Data[index].pull) + { + conf0_val.r.Pull_assign = 0x2; // PullDown + conf0_val.r.Pull_strength = 0x2;// 20K + } + else if(P_10K_H == Gpio_Conf_Data[index].pull) + { + conf0_val.r.Pull_assign = 0x1; // PullUp + conf0_val.r.Pull_strength = 0x1;// 10K + } + else if(P_10K_L == Gpio_Conf_Data[index].pull) + { + conf0_val.r.Pull_assign = 0x2; // PullDown + conf0_val.r.Pull_strength = 0x1;// 10K + } + else if(P_2K_H == Gpio_Conf_Data[index].pull) + { + conf0_val.r.Pull_assign = 0x1; // PullUp + conf0_val.r.Pull_strength = 0x0;// 2K + } + else if(P_2K_L == Gpio_Conf_Data[index].pull) + { + conf0_val.r.Pull_assign = 0x2; // PullDown + conf0_val.r.Pull_strength = 0x0;// 2K + } + else if(P_NONE == Gpio_Conf_Data[index].pull) + { + conf0_val.r.Pull_assign = 0; // Non-pull + } + else + { + ASSERT(FALSE); // Invalid value + } + } + + + // + // Set INT Trigger Type + // + conf0_val.dw &= ~0x0f000000; // Clear bits 27:24 + + // + // Set INT Trigger Type + // + if(TRIG_ == Gpio_Conf_Data[index].int_type) + { + // + // Interrupt not capable, clear bits 27:24 + // + } + else + { + conf0_val.dw |= (Gpio_Conf_Data[index].int_type & 0x0f)<<24; + } + + DEBUG ((EFI_D_INFO, "Set CONF0 = 0x%08x\n", conf0_val.dw)); + + // + // Write back the targeted GPIO config value according to platform (board) GPIO setting. + // + MmioWrite32 (mmio_conf0, conf0_val.dw); + } + + // + // A0 BIOS Spec doesn't mention it although X0 does. comment out now. + // GPIO SCORE write 0x01001002 to IOBASE + 0x0900 + // +} + +/** + Returns the Correct GPIO table for Mobile/Desktop respectively. + Before call it, make sure PlatformInfoHob->BoardId&PlatformFlavor is get correctly. + + @param PeiServices General purpose services available to every PEIM. + @param PlatformInfoHob PlatformInfoHob pointer with PlatformFlavor specified. + @param BoardId BoardId ID as determined through the EC. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_DEVICE_ERROR KSC fails to respond. + +**/ +EFI_STATUS +MultiPlatformGpioProgram ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ) +{ +#if !_SIMIC_ + CFIO_INIT_STRUCT* PlatformCfioDataPtr; + + PlatformCfioDataPtr = (CFIO_INIT_STRUCT *) (UINTN) PlatformInfoHob->PlatformCfioData; + DEBUG ((EFI_D_INFO, "MultiPlatformGpioProgram()...\n")); + + // + // SCORE GPIO WELL -- IO base registers + // + + // + // GPIO_USE_SEL Register -> 1 = GPIO 0 = Native + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL, PlatformCfioDataPtr->Use_Sel_SC0); + + // + // Set GP_LVL Register + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL , PlatformCfioDataPtr->GP_Lvl_SC0); + + // + // GP_IO_SEL Register -> 1 = Input 0 = Output. If Native Mode don't care + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_IO_SEL, PlatformCfioDataPtr->Io_Sel_SC0); + + // + // GPIO Triger Positive Edge Enable Register + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_TPE, PlatformCfioDataPtr->TPE_SC0); + + // + // GPIO Trigger Negative Edge Enable Register + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_TNE, PlatformCfioDataPtr->TNE_SC0); + + // + // GPIO Trigger Status + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_TS, PlatformCfioDataPtr->TS_SC0); + + // + // GPIO_USE_SEL2 Register -> 1 = GPIO 0 = Native + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL2, PlatformCfioDataPtr->Use_Sel_SC1); + + // + // Set GP_LVL2 Register + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL2, PlatformCfioDataPtr->GP_Lvl_SC1); + + // + // GP_IO_SEL2 Register -> 1 = Input 0 = Output. If Native Mode don't care + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_IO_SEL2, PlatformCfioDataPtr->Io_Sel_SC1); + + // + // GPIO_USE_SEL3 Register -> 1 = GPIO 0 = Native + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL3, PlatformCfioDataPtr->Use_Sel_SC2); + + // + // Set GP_LVL3 Register + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL3, PlatformCfioDataPtr->GP_Lvl_SC2); + + // + // GP_IO_SEL3 Register -> 1 = Input 0 = Output if Native Mode don't care + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_IO_SEL3, PlatformCfioDataPtr->Io_Sel_SC2); + + // + // SUS GPIO WELL -- IO base registers + // + + // + // GPIO_USE_SEL Register -> 1 = GPIO 0 = Native + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_USE_SEL, PlatformCfioDataPtr->Use_Sel_SS); + + // + // Set GP_LVL Register + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_LVL , PlatformCfioDataPtr->GP_Lvl_SS); + + // + // GP_IO_SEL Register -> 1 = Input 0 = Output. If Native Mode don't care. + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_IO_SEL, PlatformCfioDataPtr->Io_Sel_SS); + + // + // GPIO Triger Positive Edge Enable Register. + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_TPE, PlatformCfioDataPtr->TPE_SS); + + // + // GPIO Trigger Negative Edge Enable Register. + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_TNE, PlatformCfioDataPtr->TNE_SS); + + // + // GPIO Trigger Status. + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_TS, PlatformCfioDataPtr->TS_SS); + + // + // GPIO Wake Enable. + // + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_WAKE_EN, PlatformCfioDataPtr->WE_SS); + + // + // Config SC/NC/SUS GPIO Pins + // + switch (PlatformInfoHob->BoardId) { + case BOARD_ID_MINNOW2: + DEBUG ((EFI_D_INFO, "Start to config Minnow2 GPIO pins\n")); + InternalGpioConfig(GPIO_SCORE_OFFSET, sizeof(mMinnow2_GpioInitData_SC)/sizeof(mMinnow2_GpioInitData_SC[0]), (GPIO_CONF_PAD_INIT *) (UINTN) PlatformInfoHob->PlatformGpioData_SC); + InternalGpioConfig(GPIO_NCORE_OFFSET, sizeof(mMinnow2_GpioInitData_NC)/sizeof(mMinnow2_GpioInitData_NC[0]), (GPIO_CONF_PAD_INIT *) (UINTN) PlatformInfoHob->PlatformGpioData_NC); + InternalGpioConfig(GPIO_SSUS_OFFSET, sizeof(mMinnow2_GpioInitData_SUS)/sizeof(mMinnow2_GpioInitData_SUS[0]), (GPIO_CONF_PAD_INIT *) (UINTN) PlatformInfoHob->PlatformGpioData_SUS); + break; + default: + + break; + } + + // + // configure the CFIO Pnp settings + // + if (PlatformInfoHob->CfioEnabled) { + if (PlatformInfoHob->BoardId == BOARD_ID_MINNOW2){ + InternalGpioConfig(GPIO_SCORE_OFFSET, sizeof(mNB_BB_FAB3_GpioInitData_SC_TRI)/sizeof(mNB_BB_FAB3_GpioInitData_SC_TRI[0]), (GPIO_CONF_PAD_INIT *) (UINTN)PlatformInfoHob->PlatformGpioData_SC_TRI); + } + } +#else + DEBUG ((EFI_D_INFO, "Skip MultiPlatformGpioProgram()...for SIMICS or HYB model\n")); +#endif + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardGpios/BoardGpios.h b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardGpios/BoardGpios.h new file mode 100644 index 0000000000..e7d54d1fe1 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardGpios/BoardGpios.h @@ -0,0 +1,329 @@ +/**@file + Gpio setting for multiplatform. + + This file includes package header files, library classes. + + Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _BOARDGPIOS_H_ +#define _BOARDGPIOS_H_ + +#include +#include "PchAccess.h" +#include "PlatformBaseAddresses.h" +#include <../MultiPlatformLib.h> +#include +#include +#include +#include +#include +#include + + +GPIO_CONF_PAD_INIT mNB_BB_FAB3_GpioInitData_SC_TRI[] = +{ +// Pad Name GPIO Number Used As GPO Default Function# INT Capable Interrupt Type PULL H/L MMIO Offset +GPIO_INIT_ITEM("LPC_CLKOUT1 GPIOC_48 " ,TRISTS ,NA ,F0 , , ,NONE ,0x41), +GPIO_INIT_ITEM("PLT_CLK0 GPIOC_96 " ,TRISTS ,NA ,F0 , , ,NONE ,0x6a), +GPIO_INIT_ITEM("PLT_CLK3 GPIOC_99 " ,TRISTS ,NA ,F0 , , ,NONE ,0x68), +}; + +// +// Minnow2 +// +#define MINNOW2_GPIO_USE_SEL_VAL_0_31 0x00000000 +#define MINNOW2_GPIO_USE_SEL_VAL_32_63 0x00000000 +#define MINNOW2_GPIO_USE_SEL_VAL_64_70 0x00000000 +#define MINNOW2_GPIO_USE_SEL_VAL_64_70 0x00000000 +#define MINNOW2_GPIO_USE_SEL_VAL_SUS 0x00000000 +#define MINNOW2_GPIO_USE_SEL_VAL_SUS2 0x00000007 + + +#define MINNOW2_GPIO_IO_SEL_VAL_0_31 0x00000000 +#define MINNOW2_GPIO_IO_SEL_VAL_32_63 0x00000000 +#define MINNOW2_GPIO_IO_SEL_VAL_64_70 0x00000000 +#define MINNOW2_GPIO_IO_SEL_VAL_SUS 0x00000000 +#define MINNOW2_GPIO_IO_SEL_VAL_SUS2 0x00000007 + + +#define MINNOW2_GPIO_LVL_VAL_0_31 0x00000000 +#define MINNOW2_GPIO_LVL_VAL_32_63 0x00000000 +#define MINNOW2_GPIO_LVL_VAL_64_70 0x00000000 +#define MINNOW2_GPIO_LVL_VAL_SUS 0x00000000 +#define MINNOW2_GPIO_LVL_VAL_SUS2 0x00000007 + +#define MINNOW2_GPIO_TPE_VAL_0_31 0x00000000 +#define MINNOW2_GPIO_TPE_VAL_SUS 0x00000000 +#define MINNOW2_GPIO_TPE_VAL_SUS2 0x00000007 + +#define MINNOW2_GPIO_TNE_VAL_0_31 0x00000000 +#define MINNOW2_GPIO_TNE_VAL_SUS 0x00000000 +#define MINNOW2_GPIO_TNE_VAL_SUS2 0x00000007 + +#define MINNOW2_GPIO_TS_VAL_0_31 0x00000000 +#define MINNOW2_GPIO_TS_VAL_SUS 0x00000000 +#define MINNOW2_GPIO_TS_VAL_SUS2 0x00000007 + +static CFIO_INIT_STRUCT mMinnow2CfioInitData = +{ + MINNOW2_GPIO_USE_SEL_VAL_0_31, + MINNOW2_GPIO_USE_SEL_VAL_32_63, + MINNOW2_GPIO_USE_SEL_VAL_64_70, + MINNOW2_GPIO_USE_SEL_VAL_SUS, + + MINNOW2_GPIO_IO_SEL_VAL_0_31, + MINNOW2_GPIO_IO_SEL_VAL_32_63, + MINNOW2_GPIO_IO_SEL_VAL_64_70, + MINNOW2_GPIO_IO_SEL_VAL_SUS, + + MINNOW2_GPIO_LVL_VAL_0_31, + MINNOW2_GPIO_LVL_VAL_32_63, + MINNOW2_GPIO_LVL_VAL_64_70, + MINNOW2_GPIO_LVL_VAL_SUS, + + MINNOW2_GPIO_TPE_VAL_0_31, + MINNOW2_GPIO_TPE_VAL_SUS, + MINNOW2_GPIO_TNE_VAL_0_31, + MINNOW2_GPIO_TNE_VAL_SUS, + + MINNOW2_GPIO_TS_VAL_0_31, + MINNOW2_GPIO_TS_VAL_SUS +}; + +static CFIO_INIT_STRUCT mMinnow2CfioInitData2 = +{ + MINNOW2_GPIO_USE_SEL_VAL_0_31, + MINNOW2_GPIO_USE_SEL_VAL_32_63, + MINNOW2_GPIO_USE_SEL_VAL_64_70, + MINNOW2_GPIO_USE_SEL_VAL_SUS2, + + MINNOW2_GPIO_IO_SEL_VAL_0_31, + MINNOW2_GPIO_IO_SEL_VAL_32_63, + MINNOW2_GPIO_IO_SEL_VAL_64_70, + MINNOW2_GPIO_IO_SEL_VAL_SUS2, + + MINNOW2_GPIO_LVL_VAL_0_31, + MINNOW2_GPIO_LVL_VAL_32_63, + MINNOW2_GPIO_LVL_VAL_64_70, + MINNOW2_GPIO_LVL_VAL_SUS2, + + MINNOW2_GPIO_TPE_VAL_0_31, + MINNOW2_GPIO_TPE_VAL_SUS2, + MINNOW2_GPIO_TNE_VAL_0_31, + MINNOW2_GPIO_TNE_VAL_SUS2, + + MINNOW2_GPIO_TS_VAL_0_31, + MINNOW2_GPIO_TS_VAL_SUS2 +}; + +static GPIO_CONF_PAD_INIT mMinnow2_GpioInitData_NC[] = +{ +// Pad Name GPIO Number Used As GPO Default Function# INT Capable Interrupt Type PULL H/L MMIO Offset +GPIO_INIT_ITEM("HV_DDI0_HPD GPIONC_0 " ,Native ,NA ,F2 , , ,NONE ,0x13), +GPIO_INIT_ITEM("HV_DDI0_DDC_SDA GPIONC_1 " ,Native ,NA ,F2 , , ,NONE ,0x12), +GPIO_INIT_ITEM("HV_DDI0_DDC_SCL GPIONC_2 " ,Native ,NA ,F2 , , ,NONE ,0x11), +GPIO_INIT_ITEM("PANEL0_VDDEN GPIONC_3 " ,GPIO ,NA ,F0 , , ,NONE ,0x14), +GPIO_INIT_ITEM("PANEL0_BKLTEN GPIONC_4 " ,GPIO ,NA ,F0 , , ,NONE ,0x15), +GPIO_INIT_ITEM("PANEL0_BKLTCTL GPIONC_5 " ,GPIO ,NA ,F0 , , ,NONE ,0x16), +GPIO_INIT_ITEM("HV_DDI1_HPD GPIONC_6 " ,GPI ,NA ,F0 , , ,20K_L ,0x18), +GPIO_INIT_ITEM("HV_DDI1_DDC_SDA GPIONC_7 " ,Native ,NA ,F2 , , ,20K_L ,0x19), +GPIO_INIT_ITEM("HV_DDI1_DDC_SCL GPIONC_8 " ,GPI ,NA ,F0 , , ,20K_L ,0x17), +GPIO_INIT_ITEM("PANEL1_VDDEN GPIONC_9 " ,GPIO ,NA ,F0 , , ,NONE ,0x10), +GPIO_INIT_ITEM("PANEL1_BKLTEN GPIONC_10" ,GPIO ,NA ,F0 , , ,NONE ,0x0e), +GPIO_INIT_ITEM("PANEL1_BKLTCTL GPIONC_11" ,GPIO ,NA ,F0 , , ,NONE ,0x0f), +GPIO_INIT_ITEM("GP_INTD_DSI_TE1 GPIONC_12" ,GPO ,NA ,F0 , , ,NONE ,0x0c), +GPIO_INIT_ITEM("HV_DDI2_DDC_SDA GPIONC_13" ,GPI ,NA ,F0 , , ,10K_L ,0x1a), +GPIO_INIT_ITEM("HV_DDI2_DDC_SCL GPIONC_14" ,GPIO ,NA ,F0 , , ,NONE ,0x1b), +GPIO_INIT_ITEM("GP_CAMERASB00 GPIONC_15" ,GPIO ,NA ,F0 , , ,NONE ,0x01), +GPIO_INIT_ITEM("GP_CAMERASB01 GPIONC_16" ,GPIO ,NA ,F0 , , ,NONE ,0x04), +GPIO_INIT_ITEM("GP_CAMERASB02 GPIONC_17" ,GPIO ,NA ,F0 , , ,NONE ,0x08), +GPIO_INIT_ITEM("GP_CAMERASB03 GPIONC_18" ,GPIO ,NA ,F0 , , ,NONE ,0x0b), +GPIO_INIT_ITEM("GP_CAMERASB04 GPIONC_19" ,GPIO ,NA ,F0 , , ,NONE ,0x00), +GPIO_INIT_ITEM("GP_CAMERASB05 GPIONC_20" ,GPIO ,NA ,F0 , , ,NONE ,0x03), +GPIO_INIT_ITEM("GP_CAMERASB06 GPIONC_21" ,GPIO ,NA ,F0 , , ,NONE ,0x06), +GPIO_INIT_ITEM("GP_CAMERASB07 GPIONC_22" ,GPIO ,NA ,F0 , , ,NONE ,0x0a), +GPIO_INIT_ITEM("GP_CAMERASB08 GPIONC_23" ,GPIO ,NA ,F0 , , ,NONE ,0x0d), +GPIO_INIT_ITEM("GP_CAMERASB09 GPIONC_24" ,GPIO ,NA ,F0 , , ,NONE ,0x02), +GPIO_INIT_ITEM("GP_CAMERASB10 GPIONC_25" ,GPIO ,NA ,F0 , , ,NONE ,0x05), +GPIO_INIT_ITEM("GP_CAMERASB11 GPIONC_26" ,GPIO ,NA ,F0 , , ,NONE ,0x09), +}; + + +static GPIO_CONF_PAD_INIT mMinnow2_GpioInitData_SC[] = { +// Pad Name GPIO Number Used As GPO Default Function# INT Capable Interrupt Type PULL H/L MMIO Offset +GPIO_INIT_ITEM("SATA_GP0 GPIOC_0 " ,Native ,NA ,F1 , , ,NONE ,0x55), +GPIO_INIT_ITEM("SATA_GP1 GPIOC_1 " ,Native ,NA ,F1 , , ,NONE ,0x59), +GPIO_INIT_ITEM("SATA_LEDN GPIOC_2 " ,Native ,NA ,F1 , , ,NONE ,0x5d), +GPIO_INIT_ITEM("PCIE_CLKREQ0B GPIOC_3 " ,Native ,NA ,F1 , , ,10K_H ,0x60), +GPIO_INIT_ITEM("PCIE_CLKREQ1B GPIOC_4 " ,Native ,NA ,F1 , , ,10K_H ,0x63), +GPIO_INIT_ITEM("PCIE_CLKREQ2B GPIOC_5 " ,Native ,NA ,F1 , , ,10K_H ,0x66), +GPIO_INIT_ITEM("PCIE_CLKREQ3B GPIOC_6 " ,GPIO ,NA ,F0 , , ,NONE ,0x62), +GPIO_INIT_ITEM("SDMMC3_WP GPIOC_7 " ,Native ,NA ,F2 , , ,NONE ,0x65), +GPIO_INIT_ITEM("HDA_RSTB GPIOC_8 " ,GPIO ,NA ,F0 , , ,NONE ,0x22), +GPIO_INIT_ITEM("HDA_SYNC GPIOC_9 " ,GPIO ,NA ,F0 , , ,NONE ,0x25), +GPIO_INIT_ITEM("HDA_CLK GPIOC_10 " ,GPIO ,NA ,F0 , , ,NONE ,0x24), +GPIO_INIT_ITEM("HDA_SDO GPIOC_11 " ,GPIO ,NA ,F0 , , ,NONE ,0x26), +GPIO_INIT_ITEM("HDA_SDI0 GPIOC_12 " ,GPIO ,NA ,F0 , , ,NONE ,0x27), +GPIO_INIT_ITEM("HDA_SDI1 GPIOC_13 " ,GPIO ,NA ,F0 , , ,NONE ,0x23), +GPIO_INIT_ITEM("HDA_DOCKRSTB GPIOC_14 " ,GPIO ,NA ,F0 , , ,NONE ,0x28), +GPIO_INIT_ITEM("HDA_DOCKENB GPIOC_15 " ,GPIO ,NA ,F0 , , ,NONE ,0x54), +GPIO_INIT_ITEM("SDMMC1_CLK GPIOC_16 " ,GPIO ,NA ,F0 , , ,NONE ,0x3e), +GPIO_INIT_ITEM("SDMMC1_D0 GPIOC_17 " ,GPIO ,NA ,F0 , , ,NONE ,0x3d), +GPIO_INIT_ITEM("SDMMC1_D1 GPIOC_18 " ,GPIO ,NA ,F0 , , ,NONE ,0x40), +GPIO_INIT_ITEM("SDMMC1_D2 GPIOC_19 " ,GPIO ,NA ,F0 , , ,NONE ,0x3b), +GPIO_INIT_ITEM("SDMMC1_D3_CD_B GPIOC_20 " ,GPIO ,NA ,F0 , , ,NONE ,0x36), +GPIO_INIT_ITEM("MMC1_D4_SD_WE GPIOC_21 " ,GPIO ,NA ,F0 , , ,NONE ,0x38), +GPIO_INIT_ITEM("MMC1_D5 GPIOC_22 " ,GPIO ,NA ,F0 , , ,NONE ,0x3c), +GPIO_INIT_ITEM("MMC1_D6 GPIOC_23 " ,GPIO ,NA ,F0 , , ,NONE ,0x37), +GPIO_INIT_ITEM("MMC1_D7 GPIOC_24 " ,GPIO ,NA ,F0 , , ,NONE ,0x3f), +GPIO_INIT_ITEM("SDMMC1_CMD GPIOC_25 " ,GPIO ,NA ,F0 , , ,NONE ,0x39), +GPIO_INIT_ITEM("MMC1_RESET_B GPIOC_26 " ,GPIO ,NA ,F0 , , ,NONE ,0x33), +GPIO_INIT_ITEM("SDMMC2_CLK GPIOC_27 " ,GPIO ,NA ,F0 , , ,NONE ,0x32), +GPIO_INIT_ITEM("SDMMC2_D0 GPIOC_28 " ,GPIO ,NA ,F0 , , ,NONE ,0x35), +GPIO_INIT_ITEM("SDMMC2_D1 GPIOC_29 " ,GPIO ,NA ,F0 , , ,NONE ,0x2f), +GPIO_INIT_ITEM("SDMMC2_D2 GPIOC_30 " ,GPIO ,NA ,F0 , , ,NONE ,0x34), +GPIO_INIT_ITEM("SDMMC2_D3_CD_B GPIOC_31 " ,GPIO ,NA ,F0 , , ,NONE ,0x31), +GPIO_INIT_ITEM("SDMMC2_CMD GPIOC_32 " ,GPIO ,NA ,F0 , , ,NONE ,0x30), +// +//Just for test, We make the setting that all is same with Bayleybay. +// +GPIO_INIT_ITEM("SDMMC3_CLK GPIOC_33 " ,Native ,NA ,F1 , , ,NONE ,0x2b), +GPIO_INIT_ITEM("SDMMC3_D0 GPIOC_34 " ,Native ,NA ,F1 , , ,NONE ,0x2e), +GPIO_INIT_ITEM("SDMMC3_D1 GPIOC_35 " ,Native ,NA ,F1 ,YES , ,NONE ,0x29), +GPIO_INIT_ITEM("SDMMC3_D2 GPIOC_36 " ,Native ,NA ,F1 , , ,NONE ,0x2d), +GPIO_INIT_ITEM("SDMMC3_D3 GPIOC_37 " ,Native ,NA ,F1 , , ,NONE ,0x2a), +GPIO_INIT_ITEM("SDMMC3_CD_B GPIOC_38 " ,Native ,NA ,F1 ,YES ,Edge_Both ,NONE ,0x3a), +GPIO_INIT_ITEM("SDMMC3_CMD GPIOC_39 " ,Native ,NA ,F1 , , ,NONE ,0x2c), +GPIO_INIT_ITEM("SDMMC3_1P8_EN GPIOC_40 " ,Native ,NA ,F1 , , ,NONE ,0x5f), +GPIO_INIT_ITEM("SDMMC3_PWR_EN_B GPIOC_41 " ,Native ,NA ,F1 , , ,NONE ,0x69), +GPIO_INIT_ITEM("LPC_AD0 GPIOC_42 " ,GPIO ,NA ,F0 , , ,NONE ,0x46), +GPIO_INIT_ITEM("LPC_AD1 GPIOC_43 " ,GPIO ,NA ,F0 , , ,NONE ,0x44), +GPIO_INIT_ITEM("LPC_AD2 GPIOC_44 " ,GPIO ,NA ,F0 , , ,NONE ,0x43), +GPIO_INIT_ITEM("LPC_AD3 GPIOC_45 " ,GPIO ,NA ,F0 , , ,NONE ,0x42), +GPIO_INIT_ITEM("LPC_FRAMEB GPIOC_46 " ,GPIO ,NA ,F0 , , ,NONE ,0x45), +GPIO_INIT_ITEM("LPC_CLKOUT0 GPIOC_47 " ,GPIO ,NA ,F0 , , ,NONE ,0x47), +GPIO_INIT_ITEM("LPC_CLKOUT1 GPIOC_48 " ,GPIO ,NA ,F0 , , ,NONE ,0x41), +GPIO_INIT_ITEM("LPC_CLKRUNB GPIOC_49 " ,GPIO ,NA ,F0 , , ,NONE ,0x48), +GPIO_INIT_ITEM("ILB_SERIRQ GPIOC_50 " ,GPIO ,NA ,F0 , , ,NONE ,0x56), +GPIO_INIT_ITEM("SMB_DATA GPIOC_51 " ,Native ,NA ,F1 , , ,NONE ,0x5a), +GPIO_INIT_ITEM("SMB_CLK GPIOC_52 " ,Native ,NA ,F1 , , ,NONE ,0x58), +GPIO_INIT_ITEM("SMB_ALERTB GPIOC_53 " ,Native ,NA ,F1 , , ,10K_H ,0x5c), +GPIO_INIT_ITEM("SPKR GPIOC_54 " ,GPI ,NA ,F0 , , ,20K_H ,0x67), +GPIO_INIT_ITEM("MHSI_ACDATA GPIOC_55 " ,GPIO ,NA ,F0 , , ,NONE ,0x4d), +GPIO_INIT_ITEM("MHSI_ACFLAG GPIOC_56 " ,GPI ,NA ,F0 , , ,20K_H ,0x4f), +GPIO_INIT_ITEM("MHSI_ACWAKE GPIOC_58 " ,GPIO ,NA ,F0 , , ,NONE ,0x4e), +GPIO_INIT_ITEM("MHSI_CADATA GPIOC_59 " ,GPIO ,NA ,F0 , , ,NONE ,0x51), +GPIO_INIT_ITEM("MHSI_CAFLAG GPIOC_60 " ,GPO ,HI ,F0 , , ,20K_H ,0x50), +GPIO_INIT_ITEM("GP_SSP_2_CLK GPIOC_62 " ,GPI ,NA ,F0 , , ,20K_H ,0x0d), +GPIO_INIT_ITEM("GP_SSP_2_FS GPIOC_63 " ,GPI ,NA ,F0 , , ,20K_H ,0x0c), +GPIO_INIT_ITEM("GP_SSP_2_RXD GPIOC_64 " ,GPI ,NA ,F0 , , ,20K_H ,0x0f), +GPIO_INIT_ITEM("GP_SSP_2_TXD GPIOC_65 " ,GPI ,NA ,F0 , , ,20K_H ,0x0e), +GPIO_INIT_ITEM("SPI1_CS0_B GPIOC_66 " ,Native ,NA ,F1 , , ,20K_H ,0x11), +GPIO_INIT_ITEM("SPI1_MISO GPIOC_67 " ,Native ,NA ,F1 , , ,20K_H ,0x12), +GPIO_INIT_ITEM("SPI1_MOSI GPIOC_68 " ,Native ,NA ,F1 , , ,20K_H ,0x13), +GPIO_INIT_ITEM("SPI1_CLK GPIOC_69 " ,Native ,NA ,F1 , , ,20K_H ,0x10), +GPIO_INIT_ITEM("UART1_RXD GPIOC_70 " ,Native ,NA ,F1 , , ,20K_H ,0x02), +GPIO_INIT_ITEM("UART1_TXD GPIOC_71 " ,Native ,NA ,F1 , , ,20K_H ,0x01), +GPIO_INIT_ITEM("UART1_RTS_B GPIOC_72 " ,GPI ,NA ,F0 , , ,20K_H ,0x00), +GPIO_INIT_ITEM("UART1_CTS_B GPIOC_73 " ,GPI ,NA ,F0 , , ,20K_H ,0x04), +GPIO_INIT_ITEM("UART2_RXD GPIOC_74 " ,Native ,NA ,F1 , , ,20K_H ,0x06), +GPIO_INIT_ITEM("UART2_TXD GPIOC_75 " ,Native ,NA ,F1 , , ,20K_H ,0x07), +GPIO_INIT_ITEM("UART2_RTS_B GPIOC_76 " ,GPIO ,NA ,F0 , , ,NONE ,0x09), +GPIO_INIT_ITEM("UART2_CTS_B GPIOC_77 " ,Native ,NA ,F1 , , ,20K_H ,0x08), +GPIO_INIT_ITEM("I2C0_SDA GPIOC_78 " ,GPIO ,NA ,F0 , , ,NONE ,0x21), +GPIO_INIT_ITEM("I2C0_SCL GPIOC_79 " ,GPIO ,NA ,F0 , , ,NONE ,0x20), +GPIO_INIT_ITEM("I2C1_SDA GPIOC_80 " ,Native ,NA ,F1 , , ,NONE ,0x1f), +GPIO_INIT_ITEM("I2C1_SCL GPIOC_81 " ,Native ,NA ,F1 , , ,NONE ,0x1e), +GPIO_INIT_ITEM("I2C2_SDA GPIOC_82 " ,GPIO ,NA ,F0 , , ,NONE ,0x1d), +GPIO_INIT_ITEM("I2C2_SCL GPIOC_83 " ,GPIO ,NA ,F0 , , ,NONE ,0x1b), +GPIO_INIT_ITEM("I2C3_SDA GPIOC_84 " ,GPIO ,NA ,F0 , , ,NONE ,0x19), +GPIO_INIT_ITEM("I2C3_SCL GPIOC_85 " ,GPIO ,NA ,F0 , , ,NONE ,0x1c), +GPIO_INIT_ITEM("I2C4_SDA GPIOC_86 " ,Native ,NA ,F1 , , ,20K_H ,0x1a), +GPIO_INIT_ITEM("I2C4_SCL GPIOC_87 " ,GPIO ,NA ,F0 , , ,NONE ,0x17), +GPIO_INIT_ITEM("I2C5_SDA GPIOC_88 " ,Native ,NA ,F1 , , ,20K_H ,0x15), +GPIO_INIT_ITEM("I2C5_SCL GPIOC_89 " ,Native ,NA ,F1 , , ,20K_H ,0x14), +GPIO_INIT_ITEM("I2C6_SDA GPIOC_90 " ,Native ,NA ,F1 , , ,20K_H ,0x18), +GPIO_INIT_ITEM("I2C6_SCL GPIOC_91 " ,Native ,NA ,F1 , , ,20K_H ,0x16), +GPIO_INIT_ITEM("I2C_NFC_SDA GPIOC_92 " ,GPIO ,NA ,F1 , , ,NONE ,0x05), +GPIO_INIT_ITEM("I2C_NFC_SCL GPIOC_93 " ,GPO ,LO ,F1 , , ,NONE ,0x03), +GPIO_INIT_ITEM("PWM0 GPIOC_94 " ,Native ,NA ,F1 , , ,20K_L ,0x0a), +GPIO_INIT_ITEM("PWM1 GPIOC_95 " ,Native ,NA ,F1 , , ,20K_L ,0x0b), +GPIO_INIT_ITEM("PLT_CLK0 GPIOC_96 " ,GPIO ,NA ,F0 , , ,NONE ,0x6a), +GPIO_INIT_ITEM("PLT_CLK1 GPIOC_97 " ,GPIO ,NA ,F0 , , ,NONE ,0x57), +GPIO_INIT_ITEM("PLT_CLK2 GPIOC_98 " ,GPIO ,NA ,F0 , , ,NONE ,0x5b), +GPIO_INIT_ITEM("PLT_CLK3 GPIOC_99 " ,GPIO ,NA ,F0 , , ,NONE ,0x68), +GPIO_INIT_ITEM("PLT_CLK4 GPIOC_100" ,GPIO ,NA ,F0 , , ,NONE ,0x61), +GPIO_INIT_ITEM("PLT_CLK5 GPIOC_101" ,GPIO ,NA ,F0 , , ,NONE ,0x64), +}; + +static GPIO_CONF_PAD_INIT mMinnow2_GpioInitData_SUS[] = { +// Pad Name GPIO Number Used As GPIO Default Function# INT Capable Interrupt Type PULL H/L MMIO Offset +GPIO_INIT_ITEM("GPIO_SUS0 GPIO_SUS0" ,GPI ,NA ,F0 , , ,20K_H ,0x1d), +GPIO_INIT_ITEM("GPIO_SUS1 GPIO_SUS1" ,GPI ,NA ,F0 , , ,20K_H ,0x21), +GPIO_INIT_ITEM("GPIO_SUS2 GPIO_SUS2" ,GPI ,NA ,F0 , , ,20K_H ,0x1e), +GPIO_INIT_ITEM("GPIO_SUS3 GPIO_SUS3" ,Native ,NA ,F6 ,YES ,Level_Low ,2K_H ,0x1f), +GPIO_INIT_ITEM("GPIO_SUS4 GPIO_SUS4" ,GPIO ,NA ,F0 , , ,NONE ,0x20), +GPIO_INIT_ITEM("GPIO_SUS5 GPIO_SUS5" ,GPI ,NA ,F0 , , ,NONE ,0x22), +GPIO_INIT_ITEM("GPIO_SUS6 GPIO_SUS6" ,GPI ,NA ,F0 , , ,NONE ,0x24), +GPIO_INIT_ITEM("GPIO_SUS7 GPIO_SUS7" ,GPI ,NA ,F0 , , ,NONE ,0x23), +GPIO_INIT_ITEM("SEC_GPIO_SUS8 GPIO_SUS8" ,GPO ,HI ,F0 , , ,20K_H ,0x26), +GPIO_INIT_ITEM("SEC_GPIO_SUS9 GPIO_SUS9" ,GPO ,HI ,F0 , , ,20K_H ,0x25), +GPIO_INIT_ITEM("SEC_GPIO_SUS10 GPIO_SUS10" ,GPO ,HI ,F0 , , ,NONE ,0x12), +GPIO_INIT_ITEM("SUSPWRDNACK GPIOS_11 " ,Native ,NA ,F0 , , ,10K_H ,0x07), +GPIO_INIT_ITEM("PMU_SUSCLK GPIOS_12 " ,Native ,NA ,F0 , , ,NONE ,0x0b), +GPIO_INIT_ITEM("PMU_SLP_S0IX_B GPIOS_13 " ,Native ,NA ,F0 , , ,NONE ,0x14), +GPIO_INIT_ITEM("PMU_SLP_LAN_B GPIOS_14 " ,GPO ,LO ,F1 , , ,10K_H ,0x11), +GPIO_INIT_ITEM("PMU_WAKE_B GPIOS_15 " ,Native ,NA ,F0 , , ,20K_H ,0x01), +GPIO_INIT_ITEM("PMU_PWRBTN_B GPIOS_16 " ,Native ,NA ,F0 , , ,20K_H ,0x08), +GPIO_INIT_ITEM("PMU_WAKE_LAN_B GPIOS_17 " ,GPIO ,NA ,F1 , , ,NONE ,0x0a), +GPIO_INIT_ITEM("SUS_STAT_B GPIOS_18 " ,GPO ,NA ,F1 , , ,NONE ,0x13), +GPIO_INIT_ITEM("USB_OC0_B GPIOS_19 " ,Native ,NA ,F0 , , ,10K_H ,0x0c), +GPIO_INIT_ITEM("USB_OC1_B GPIOS_20 " ,Native ,NA ,F0 , , ,10K_H ,0x00), +GPIO_INIT_ITEM("SPI_CS1_B GPIOS_21 " ,Native ,NA ,F0 , , ,NONE ,0x02), +GPIO_INIT_ITEM("GPIO_DFX0 GPIOS_22 " ,GPIO ,NA ,F0 , , ,NONE ,0x17), +GPIO_INIT_ITEM("GPIO_DFX1 GPIOS_23 " ,GPIO ,NA ,F0 , , ,NONE ,0x27), +GPIO_INIT_ITEM("GPIO_DFX2 GPIOS_24 " ,GPIO ,NA ,F0 , , ,NONE ,0x1c), +GPIO_INIT_ITEM("GPIO_DFX3 GPIOS_25 " ,GPIO ,NA ,F0 , , ,NONE ,0x1b), +GPIO_INIT_ITEM("GPIO_DFX4 GPIOS_26 " ,GPIO ,NA ,F0 , , ,NONE ,0x16), +GPIO_INIT_ITEM("GPIO_DFX5 GPIOS_27 " ,GPI ,NA ,F0 , , ,20K_H ,0x15), +GPIO_INIT_ITEM("GPIO_DFX6 GPIOS_28 " ,GPI ,NA ,F0 , , ,20K_H ,0x18), +GPIO_INIT_ITEM("GPIO_DFX7 GPIOS_29 " ,GPI ,NA ,F0 , , ,20K_H ,0x19), +GPIO_INIT_ITEM("GPIO_DFX8 GPIOS_30 " ,GPI ,NA ,F0 , , ,20K_H ,0x1a), +GPIO_INIT_ITEM("USB_ULPI_0_CLK GPIOS_31 " ,GPIO ,NA ,F0 , , ,NONE ,0x33), +GPIO_INIT_ITEM("USB_ULPI_0_DATA0 GPIOS_32 " ,GPIO ,NA ,F0 , , ,NONE ,0x38), +GPIO_INIT_ITEM("USB_ULPI_0_DATA1 GPIOS_33 " ,GPIO ,NA ,F0 , , ,NONE ,0x36), +GPIO_INIT_ITEM("USB_ULPI_0_DATA2 GPIOS_34 " ,GPIO ,NA ,F0 , , ,NONE ,0x31), +GPIO_INIT_ITEM("USB_ULPI_0_DATA3 GPIOS_35 " ,GPIO ,NA ,F0 , , ,NONE ,0x37), +GPIO_INIT_ITEM("USB_ULPI_0_DATA4 GPIOS_36 " ,GPIO ,NA ,F0 , , ,NONE ,0x30), +GPIO_INIT_ITEM("USB_ULPI_0_DATA5 GPIOS_37 " ,GPIO ,NA ,F0 , , ,NONE ,0x39), +GPIO_INIT_ITEM("USB_ULPI_0_DATA6 GPIOS_38 " ,GPIO ,NA ,F0 , , ,NONE ,0x32), +GPIO_INIT_ITEM("USB_ULPI_0_DATA7 GPIOS_39 " ,GPIO ,NA ,F0 , , ,NONE ,0x3a), +GPIO_INIT_ITEM("USB_ULPI_0_DIR GPIOS_40 " ,GPIO ,NA ,F0 , , ,NONE ,0x34), +GPIO_INIT_ITEM("USB_ULPI_0_NXT GPIOS_41 " ,GPIO ,NA ,F0 , , ,NONE ,0x35), +GPIO_INIT_ITEM("USB_ULPI_0_STP GPIOS_42 " ,GPIO ,NA ,F0 , , ,NONE ,0x3b), +GPIO_INIT_ITEM("USB_ULPI_0_REFCLK GPIOS_43 " ,GPIO ,NA ,F0 , , ,NONE ,0x28), +}; + +EFI_STATUS +MultiPlatformGpioTableInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ); + +EFI_STATUS +MultiPlatformGpioProgram ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardJumpers/BoardJumpers.c b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardJumpers/BoardJumpers.c new file mode 100644 index 0000000000..6862c63c5d --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardJumpers/BoardJumpers.c @@ -0,0 +1,35 @@ +/** @file + Jumper setting for multiplatform. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include + +BOOLEAN +IsRecoveryJumper ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob +) +{ + return FALSE; +} + +BOOLEAN +IsManufacturingMode( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob +) +{ + return FALSE; +} diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardJumpers/BoardJumpers.h b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardJumpers/BoardJumpers.h new file mode 100644 index 0000000000..e93d55cd3d --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardJumpers/BoardJumpers.h @@ -0,0 +1,35 @@ +/**@file + Jumper setting for multiplatform. + + This file includes package header files, library classes. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _BOARDJUMPERS_H_ +#define _BOARDJUMPERS_H_ + +#include +#include "PchAccess.h" +#include "PlatformBaseAddresses.h" + +#include +#include +#include + +BOOLEAN +IsRecoveryJumper ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob +); + +#endif diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardOemIds/BoardOemIds.c b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardOemIds/BoardOemIds.c new file mode 100644 index 0000000000..7381e00875 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardOemIds/BoardOemIds.c @@ -0,0 +1,47 @@ +/** @file + ACPI oem ids setting for multiplatform. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include + +// +// Global module data +// +EFI_STATUS +InitializeBoardOemId ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ) +{ + UINT64 OemId; + UINT64 OemTableId; + + // + // Set OEM ID according to Board ID. + // + switch (PlatformInfoHob->BoardId) { + + case BOARD_ID_MINNOW2: + default: + OemId = EFI_ACPI_OEM_ID_DEFAULT; + OemTableId = EFI_ACPI_OEM_TABLE_ID_DEFAULT; + break; + } + + PlatformInfoHob->AcpiOemId = OemId; + PlatformInfoHob->AcpiOemTableId = OemTableId; + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardOemIds/BoardOemIds.h b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardOemIds/BoardOemIds.h new file mode 100644 index 0000000000..d8da53f111 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardOemIds/BoardOemIds.h @@ -0,0 +1,34 @@ +/**@file + ACPI oem ids setting for multiplatform. + + This file includes package header files, library classes. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +#define EFI_ACPI_OEM_ID_DEFAULT SIGNATURE_64('I', 'N', 'T', 'E', 'L', ' ', ' ', ' ') // max 6 chars +#define EFI_ACPI_OEM_ID1 SIGNATURE_64('I', 'N', 'T', 'E', 'L', '1', ' ', ' ') // max 6 chars +#define EFI_ACPI_OEM_ID2 SIGNATURE_64('I', 'N', 'T', 'E', 'L', '2', ' ', ' ') // max 6 chars + +#define EFI_ACPI_OEM_TABLE_ID_DEFAULT SIGNATURE_64('E', 'D', 'K', '2', ' ', ' ', ' ', ' ') +#define EFI_ACPI_OEM_TABLE_ID1 SIGNATURE_64('E', 'D', 'K', '2', '_', '1', ' ', ' ') +#define EFI_ACPI_OEM_TABLE_ID2 SIGNATURE_64('E', 'D', 'K', '2', '_', '2', ' ', ' ') + + +EFI_STATUS +InitializeBoardOemId ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ); diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardSsidSvid/BoardSsidSvid.c b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardSsidSvid/BoardSsidSvid.c new file mode 100644 index 0000000000..4a05d313f8 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardSsidSvid/BoardSsidSvid.c @@ -0,0 +1,42 @@ +/** @file + Subsystem IDs setting for multiplatform. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include + +// +// Global module data +// +EFI_STATUS +InitializeBoardSsidSvid ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ) +{ + UINT32 SsidSvidValue = 0; + + // + // Set OEM ID according to Board ID. + // + switch (PlatformInfoHob->BoardId) { + case BOARD_ID_MINNOW2: + default: + SsidSvidValue = SUBSYSTEM_SVID_SSID;//SUBSYSTEM_SVID_SSID_DEFAULT; + break; + } + PlatformInfoHob->SsidSvid = SsidSvidValue; + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardSsidSvid/BoardSsidSvid.h b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardSsidSvid/BoardSsidSvid.h new file mode 100644 index 0000000000..b22c03c804 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardSsidSvid/BoardSsidSvid.h @@ -0,0 +1,40 @@ +/**@file + Subsystem IDs setting for multiplatform. + + This file includes package header files, library classes. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +// +// Default Vendor ID and Subsystem ID +// +#define SUBSYSTEM_VENDOR_ID1 0x8086 +#define SUBSYSTEM_DEVICE_ID1 0x1999 +#define SUBSYSTEM_SVID_SSID1 (SUBSYSTEM_VENDOR_ID1 + (SUBSYSTEM_DEVICE_ID1 << 16)) + +#define SUBSYSTEM_VENDOR_ID2 0x8086 +#define SUBSYSTEM_DEVICE_ID2 0x1888 +#define SUBSYSTEM_SVID_SSID2 (SUBSYSTEM_VENDOR_ID2 + (SUBSYSTEM_DEVICE_ID2 << 16)) + +#define SUBSYSTEM_VENDOR_ID 0x8086 +#define SUBSYSTEM_DEVICE_ID 0x1234 +#define SUBSYSTEM_SVID_SSID (SUBSYSTEM_VENDOR_ID + (SUBSYSTEM_DEVICE_ID << 16)) + +EFI_STATUS +InitializeBoardSsidSvid ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ); diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/MultiPlatformLib.c b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/MultiPlatformLib.c new file mode 100644 index 0000000000..d32deb5b6c --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/MultiPlatformLib.c @@ -0,0 +1,122 @@ +/** @file + Multiplatform initialization. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include + +/** + 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. + + @param FfsHeader Pointer to Firmware File System file header. + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS Memory initialization completed successfully. + @retval Others All other error conditions encountered result in an ASSERT. + +**/ +EFI_STATUS +MultiPlatformInfoInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ) +{ + UINT32 PcieLength; + EFI_STATUS Status; + + + PlatformInfoHob->IohSku = MmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET); + + PlatformInfoHob->IohRevision = MmPci8(0, MC_BUS, MC_DEV, MC_FUN, PCI_REVISION_ID_OFFSET); + + // + // Update ICH Type + // + // + // Device ID + // + PlatformInfoHob->IchSku = PchLpcPciCfg16(PCI_DEVICE_ID_OFFSET); + + PlatformInfoHob->IchRevision = PchLpcPciCfg8(PCI_REVISION_ID_OFFSET); + + // + //64MB + // + PcieLength = 0x04000000; + + // + // Don't support BASE above 4GB currently. + // + PlatformInfoHob->PciData.PciExpressSize = PcieLength; + PlatformInfoHob->PciData.PciExpressBase = PcdGet64 (PcdPciExpressBaseAddress); + + PlatformInfoHob->PciData.PciResourceMem32Base = (UINT32) (PlatformInfoHob->PciData.PciExpressBase - RES_MEM32_MIN_LEN); + PlatformInfoHob->PciData.PciResourceMem32Limit = (UINT32) (PlatformInfoHob->PciData.PciExpressBase -1); + + PlatformInfoHob->PciData.PciResourceMem64Base = RES_MEM64_36_BASE; + PlatformInfoHob->PciData.PciResourceMem64Limit = RES_MEM64_36_LIMIT; + PlatformInfoHob->CpuData.CpuAddressWidth = 36; + + PlatformInfoHob->MemData.MemMir0 = PlatformInfoHob->PciData.PciResourceMem64Base; + PlatformInfoHob->MemData.MemMir1 = PlatformInfoHob->PciData.PciResourceMem64Limit + 1; + + PlatformInfoHob->PciData.PciResourceMinSecBus = 1; //can be changed by SystemConfiguration->PciMinSecondaryBus; + + // + // Set MemMaxTolm to the lowest address between PCIe Base and PCI32 Base. + // + if (PlatformInfoHob->PciData.PciExpressBase > PlatformInfoHob->PciData.PciResourceMem32Base ) { + PlatformInfoHob->MemData.MemMaxTolm = (UINT32) PlatformInfoHob->PciData.PciResourceMem32Base; + } else { + PlatformInfoHob->MemData.MemMaxTolm = (UINT32) PlatformInfoHob->PciData.PciExpressBase; + } + PlatformInfoHob->MemData.MemTolm = PlatformInfoHob->MemData.MemMaxTolm; + + // + // Platform PCI MMIO Size in unit of 1MB. + // + PlatformInfoHob->MemData.MmioSize = 0x1000 - (UINT16)(PlatformInfoHob->MemData.MemMaxTolm >> 20); + + // + // Enable ICH IOAPIC + // + PlatformInfoHob->SysData.SysIoApicEnable = ICH_IOAPIC; + + DEBUG ((EFI_D_ERROR, "PlatformFlavor is %x (%x=tablet,%x=mobile,%x=desktop)\n", PlatformInfoHob->PlatformFlavor,FlavorTablet,FlavorMobile,FlavorDesktop)); + + // + // Get Platform Info and fill the Hob. + // + PlatformInfoHob->RevisonId = PLATFORM_INFO_HOB_REVISION; + + // + // Get GPIO table + // + Status = MultiPlatformGpioTableInit (PeiServices, PlatformInfoHob); + + // + // Program GPIO + // + Status = MultiPlatformGpioProgram (PeiServices, PlatformInfoHob); + + // + // Update OemId + // + Status = InitializeBoardOemId (PeiServices, PlatformInfoHob); + Status = InitializeBoardSsidSvid (PeiServices, PlatformInfoHob); + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/MultiPlatformLib.h b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/MultiPlatformLib.h new file mode 100644 index 0000000000..a1fe9d4356 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/MultiPlatformLib.h @@ -0,0 +1,94 @@ +/**@file + Multiplatform initialization header file. + + This file includes package header files, library classes. + + Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MULTIPLATFORM_LIB_H_ +#define _MULTIPLATFORM_LIB_H_ + + +#define LEN_64M 0x4000000 + +// +// Default PCI32 resource size +// +#define RES_MEM32_MIN_LEN 0x38000000 + +#define RES_IO_BASE 0x0D00 +#define RES_IO_LIMIT 0xFFFF + +#include +#include +#include + +#include "PlatformBaseAddresses.h" +#include "PchAccess.h" +#include "SetupMode.h" +#include "PlatformBootMode.h" +#include "Platform.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +EFI_STATUS +GetPlatformInfoHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT EFI_PLATFORM_INFO_HOB **PlatformInfoHob + ); + +EFI_STATUS +MultiPlatformGpioTableInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ); + +EFI_STATUS +MultiPlatformGpioProgram ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/MultiPlatformLib.inf b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/MultiPlatformLib.inf new file mode 100644 index 0000000000..74ffc78c91 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/MultiPlatformLib.inf @@ -0,0 +1,83 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +# Module Name: +# +# MultiPlatform.inf +# +# Abstract: +# +# +--*/ + + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = MultiPlatformLib + FILE_GUID = AB83A52B-B44A-462c-B099-444CC0ED274D + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = MultiPlatformLib + PI_SPECIFICATION_VERSION = 0x0001000A + +[sources] + MultiPlatformLib.c + MultiPlatformLib.h + PlatformInfoHob.c +#GPIO + BoardGpios/BoardGpios.c + BoardGpios/BoardGpios.h + +#ClkGen + BoardClkGens/BoardClkGens.c + BoardClkGens/BoardClkGens.h + +#Jumper + BoardJumpers/BoardJumpers.c + BoardJumpers/BoardJumpers.h + +#OemId + BoardOemIds/BoardOemIds.c + BoardOemIds/BoardOemIds.h + +#SSIDSVID + BoardSsidSvid/BoardSsidSvid.c + BoardSsidSvid/BoardSsidSvid.h +[Guids] + + gEfiPlatformInfoGuid # ALWAYS_CONSUMED + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + IA32FamilyCpuPkg/IA32FamilyCpuPkg.dec + +[LibraryClasses] + DebugLib + HobLib + IoLib +# PeiKscLib + +[Ppis] + gEfiPeiReadOnlyVariable2PpiGuid + +[Pcd.common] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + +[Guids] + gEfiSetupVariableGuid diff --git a/Vlv2TbltDevicePkg/Library/MultiPlatformLib/PlatformInfoHob.c b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/PlatformInfoHob.c new file mode 100644 index 0000000000..ebaaf40a16 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/MultiPlatformLib/PlatformInfoHob.c @@ -0,0 +1,59 @@ +/** @file + Platform Hob access interface for multiplatform. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include + +/** + Returns the Platform Info of the platform from the HOB. + + @param PeiServices General purpose services available to every PEIM. + @param PlatformInfoHob Pointer to the PLATFORM_INFO_HOB Pointer + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND PlatformInfoHob data doesn't exist, use default instead. + +**/ +EFI_STATUS +GetPlatformInfoHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT EFI_PLATFORM_INFO_HOB **PlatformInfoHob + ) +{ + EFI_PEI_HOB_POINTERS GuidHob; + + // + // Find the PlatformInfo HOB + // + GuidHob.Raw = GetHobList (); + if (GuidHob.Raw == NULL) { + return EFI_NOT_FOUND; + } + + if ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformInfoGuid, GuidHob.Raw)) != NULL) { + *PlatformInfoHob = GET_GUID_HOB_DATA (GuidHob.Guid); + } + + // + // PlatformInfo PEIM should provide this HOB data, if not ASSERT and return error. + // + ASSERT_EFI_ERROR (*PlatformInfoHob != NULL); + if (!(*PlatformInfoHob)) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLib.inf b/Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLib.inf new file mode 100644 index 0000000000..48386cb2d4 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLib.inf @@ -0,0 +1,55 @@ +# +# +#/*++ +# +# Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# Module Name: +# +# PeiDxePchPlatformLib.inf +# +# Abstract: +# +# Component description file for PEI/DXE PCH Platform Lib +# +#--*/ + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = PchPlatformLib + FILE_GUID = 32F89CBC-305D-4bdd-8B2C-9C65592E66AC + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PchPlatformLib + +[sources.common] + PchPlatformLibrary.h + PchPlatformLibrary.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + +[LibraryClasses] + BaseLib + PciLib + IoLib + DebugLib + + +[Pcd.common] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + + +[Protocols] + diff --git a/Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLibrary.c b/Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLibrary.c new file mode 100644 index 0000000000..c92308f4e9 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLibrary.c @@ -0,0 +1,131 @@ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + @file + PchPlatformLib.c + + @brief + PCH Platform Lib implementation. + +**/ + +#include "PchPlatformLibrary.h" + +// +// Silicon Steppings +// +/** + Return Pch stepping type + + @param[in] None + + @retval PCH_STEPPING Pch stepping type + +**/ +PCH_STEPPING +EFIAPI +PchStepping ( + VOID + ) +{ + UINT8 RevId; + + RevId = MmioRead8 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_RID_CC) + ); + + switch (RevId) { + case V_PCH_LPC_RID_0: + case V_PCH_LPC_RID_1: + return PchA0; + break; + + case V_PCH_LPC_RID_2: + case V_PCH_LPC_RID_3: + return PchA1; + break; + + case V_PCH_LPC_RID_4: + case V_PCH_LPC_RID_5: + return PchB0; + break; + + case V_PCH_LPC_RID_6: + case V_PCH_LPC_RID_7: + return PchB1; + break; + + case V_PCH_LPC_RID_8: + case V_PCH_LPC_RID_9: + return PchB2; + break; + + case V_PCH_LPC_RID_A: + case V_PCH_LPC_RID_B: + return PchB3; + break; + + case V_PCH_LPC_RID_C: + case V_PCH_LPC_RID_D: + return PchC0; + break; + + default: + return PchSteppingMax; + break; + + } +} + +/** + Determine if PCH is supported + + @param[in] None + + @retval TRUE PCH is supported + @retval FALSE PCH is not supported + +**/ +BOOLEAN +IsPchSupported ( + VOID + ) +{ + UINT32 Identifiers; + UINT16 PcuVendorId; + UINT16 PcuDeviceId; + + Identifiers = MmioRead32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_REG_ID) + ); + + PcuDeviceId = (UINT16) ((Identifiers & B_PCH_LPC_DEVICE_ID) >> 16); + PcuVendorId = (UINT16) (Identifiers & B_PCH_LPC_VENDOR_ID); + + // + // Verify that this is a supported chipset + // + if (PcuVendorId != (UINT16) V_PCH_LPC_VENDOR_ID || !IS_PCH_VLV_LPC_DEVICE_ID (PcuDeviceId)) { + DEBUG ((EFI_D_ERROR, "VLV SC code doesn't support the PcuDeviceId: 0x%04x!\n", PcuDeviceId)); + return FALSE; + } + return TRUE; +} diff --git a/Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLibrary.h b/Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLibrary.h new file mode 100644 index 0000000000..74649003d7 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLibrary.h @@ -0,0 +1,40 @@ +/** +**/ +/** + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + @file + PchPlatformLibrary.h + + @brief + Header file for PCH Platform Lib implementation. + +**/ + +#ifndef _PCH_PLATFORM_LIBRARY_IMPLEMENTATION_H_ +#define _PCH_PLATFORM_LIBRARY_IMPLEMENTATION_H_ + +#include "PchAccess.h" +#ifdef ECP_FLAG +#include "EdkIIGlueBase.h" +#include "Library/EdkIIGlueMemoryAllocationLib.h" +#else +#include "Library/PciLib.h" +#include "Library/IoLib.h" +#include "Library/DebugLib.h" +#include "Library/PcdLib.h" + +#include "PchCommonDefinitions.h" +#endif + +#endif diff --git a/Vlv2TbltDevicePkg/Library/PchSmmLib/CommonHeader.h b/Vlv2TbltDevicePkg/Library/PchSmmLib/CommonHeader.h new file mode 100644 index 0000000000..aefb5c2b6d --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PchSmmLib/CommonHeader.h @@ -0,0 +1,37 @@ +/**@file + Common header file shared by all source files. + + This file includes package header files, library classes and protocol, PPI & GUID definitions. + + Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + +#include + +#include +#include +#include +#include +#include + +#define R_PCH_ACPI_SMI_EN 0x30 +#define B_PCH_ACPI_APMC_EN 0x00000020 +#define B_PCH_ACPI_EOS 0x00000002 +#define B_PCH_ACPI_GBL_SMI_EN 0x00000001 +#define R_PCH_ACPI_SMI_STS 0x34 +#define B_PCH_ACPI_APM_STS 0x00000020 + +#endif diff --git a/Vlv2TbltDevicePkg/Library/PchSmmLib/PchSmmLib.c b/Vlv2TbltDevicePkg/Library/PchSmmLib/PchSmmLib.c new file mode 100644 index 0000000000..d4a90ee02d --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PchSmmLib/PchSmmLib.c @@ -0,0 +1,162 @@ +/** @file + PCH Smm Library Services that implements both S/W SMI generation and detection. + + Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + + +#include "CommonHeader.h" + + +/** + 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 + ) +{ + ASSERT(FALSE); +} + + +/** + Triggers an SMI at boot time. + + This function triggers a software SMM interrupt at boot time. + +**/ +VOID +EFIAPI +TriggerBootServiceSoftwareSmi ( + VOID + ) +{ + ASSERT(FALSE); +} + + +/** + Triggers an SMI at run time. + + This function triggers a software SMM interrupt at run time. + +**/ +VOID +EFIAPI +TriggerRuntimeSoftwareSmi ( + VOID + ) +{ + ASSERT(FALSE); +} + + +/** + 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 + ) +{ + ASSERT(FALSE); + 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 + ) +{ + ASSERT(FALSE); + return FALSE; +} + + +/** + 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 + ) +{ + ASSERT(FALSE); + return FALSE; +} + + +/** + + Clear APM SMI Status Bit; Set the EOS bit. + +**/ +VOID +EFIAPI +ClearSmi ( + VOID + ) +{ + + UINT16 PmBase; + + // + // Get PMBase + // + PmBase = PcdGet16 (PcdPchAcpiIoPortBaseAddress); + + // + // Clear the APM SMI Status Bit + // + IoWrite16 (PmBase + R_PCH_ACPI_SMI_STS, B_PCH_ACPI_APM_STS); + + // + // Set the EOS Bit + // + IoOr32 (PmBase + R_PCH_ACPI_SMI_EN, B_PCH_ACPI_EOS); +} + diff --git a/Vlv2TbltDevicePkg/Library/PchSmmLib/PchSmmLib.inf b/Vlv2TbltDevicePkg/Library/PchSmmLib/PchSmmLib.inf new file mode 100644 index 0000000000..e6516fbb3d --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PchSmmLib/PchSmmLib.inf @@ -0,0 +1,51 @@ +## @file +# Component description file for Intel Ich7 SMM Library. +# +# ICH SMM Library that layers on top of the I/O Library to directly +# access SMM power management registers. +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PchSmmLib + FILE_GUID = A6A16CCB-91B0-42f4-B4F3-D17D7A5662E6 + 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] + PchSmmLib.c + + +[Packages] + MdePkg/MdePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + +[LibraryClasses] + PcdLib + IoLib + +[Pcd] + gEfiPchTokenSpaceGuid.PcdPchAcpiIoPortBaseAddress + + diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c new file mode 100644 index 0000000000..b0ada79f02 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c @@ -0,0 +1,2399 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + BdsPlatform.c + +Abstract: + + This file include all platform action which can be customized + by IBV/OEM. + +--*/ + +#include "BdsPlatform.h" +#include "SetupMode.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "PchAccess.h" +#include "PchRegs/PchRegsSata.h" +#include +#include + + +EFI_GUID *ConnectDriverTable[] = { + &gEfiMmioDeviceProtocolGuid, + &gEfiI2cMasterProtocolGuid, + &gEfiI2cHostProtocolGuid +}; + +#define SHELL_ENVIRONMENT_INTERFACE_PROTOCOL \ + { \ + 0x47c7b221, 0xc42a, 0x11d2, 0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b \ + } +VOID *mShellImageCallbackReg = NULL; + + + +EFI_USER_PROFILE_HANDLE mCurrentUser = NULL; +EFI_EVENT mHotKeyTimerEvent = NULL; +EFI_EVENT mHitHotkeyEvent = NULL; +EFI_EVENT mUsbKeyboardConnectEvent = NULL; +BOOLEAN mHotKeyPressed = FALSE; +VOID *mHitHotkeyRegistration; +#define KEYBOARD_TIMER_INTERVAL 20000 // 0.02s + +VOID +ConnectUSBController ( + VOID + ); + +EFI_STATUS +PlatformBdsConnectSimpleConsole ( + IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole +); + +VOID +BootIntoFirmwareInterface( + VOID + ); + +VOID +EFIAPI +PlatformBdsInitHotKeyEvent ( + VOID + ); + +VOID +EFIAPI +DisableAhciCtlr ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT32 PmcDisableAddress; + UINT8 SataStorageAmount; + UINT32 SataBase; + UINT16 SataPortStatus; + + + DEBUG ((EFI_D_INFO, "Disable AHCI event is signalled\n")); + SataStorageAmount = 0; + SataBase = *(UINT32*) Context; + + // + // BayTrail-M EDS chapter 16 ---- PCI IO Register Offset 92 (SATA Port Control and Status) + // + SataPortStatus = MmioRead16 (SataBase + R_PCH_SATA_PCS); + + // + // Bit 8 EN: Port 0 Present + // + if ((SataPortStatus & 0x100) == 0x100) { + SataStorageAmount++; + } + + // + // Bit 9 EN: Port 1 Present + // + if ((SataPortStatus & 0x200) == 0x200) { + SataStorageAmount++; + } + + // + // Disable SATA controller when it sets to AHCI mode without carrying any devices + // in order to prevent AHCI yellow bang under Win device manager. + // + if (SataStorageAmount == 0) { + PmcDisableAddress = (MmioRead32 ((PCH_PCI_EXPRESS_BASE_ADDRESS + (UINT32) (31 << 15)) + R_PCH_LPC_PMC_BASE) & B_PCH_LPC_PMC_BASE_BAR) + R_PCH_PMC_FUNC_DIS; + MmioOr32 (PmcDisableAddress, B_PCH_PMC_FUNC_DIS_SATA); + S3BootScriptSaveMemWrite ( + EfiBootScriptWidthUint32, + (UINTN) PmcDisableAddress, + 1, + (VOID *) (UINTN) PmcDisableAddress + ); + } +} + +VOID +InstallReadyToLock ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_SMM_ACCESS2_PROTOCOL *SmmAccess; + EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save; + + // + // Install DxeSmmReadyToLock protocol prior to the processing of boot options + // + Status = gBS->LocateProtocol ( + &gEfiSmmAccess2ProtocolGuid, + NULL, + (VOID **) &SmmAccess + ); + if (!EFI_ERROR (Status)) { + + // + // Prepare S3 information, this MUST be done before DxeSmmReadyToLock + // + Status = gBS->LocateProtocol ( + &gEfiAcpiS3SaveProtocolGuid, + NULL, + (VOID **)&AcpiS3Save + ); + if (!EFI_ERROR (Status)) { + AcpiS3Save->S3Save (AcpiS3Save, NULL); + } + + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gExitPmAuthProtocolGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiDxeSmmReadyToLockProtocolGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + + return ; +} + +VOID +EFIAPI +ShellImageCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + BdsSetConsoleMode (TRUE); + DEBUG ((EFI_D_INFO, "BdsEntry ShellImageCallback \n")); +} + +// +// BDS Platform Functions +// +/** + Platform Bds init. Incude the platform firmware vendor, revision + and so crc check. + + @param VOID + + @retval None. + +**/ +VOID +EFIAPI +PlatformBdsInit ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT ShellImageEvent; + EFI_GUID ShellEnvProtocol = SHELL_ENVIRONMENT_INTERFACE_PROTOCOL; + + #ifdef __GNUC__ + SerialPortWrite((UINT8 *)">>>>BdsEntry[GCC]\r\n", 19); + #else + SerialPortWrite((UINT8 *)">>>>BdsEntry\r\n", 14); + #endif + BdsLibSaveMemoryTypeInformation (); + + // + // Before user authentication, the user identification devices need be connected + // from the platform customized device paths + // + PlatformBdsConnectAuthDevice (); + + // + // As console is not ready, the auto logon user will be identified. + // + BdsLibUserIdentify (&mCurrentUser); + + // + // Change Gop mode when boot into Shell + // + if (mShellImageCallbackReg == NULL) { + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + ShellImageCallback, + NULL, + &ShellImageEvent + ); + if (!EFI_ERROR (Status)) { + Status = gBS->RegisterProtocolNotify ( + &ShellEnvProtocol, + ShellImageEvent, + &mShellImageCallbackReg + ); + + DEBUG ((EFI_D_INFO, "BdsEntry ShellImageCallback \n")); + } + } +} + +EFI_STATUS +GetGopDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath, + OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath + ) +{ + UINTN Index; + EFI_STATUS Status; + EFI_HANDLE PciDeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath; + UINTN GopHandleCount; + EFI_HANDLE *GopHandleBuffer; + + UINTN VarSize; + SYSTEM_CONFIGURATION mSystemConfiguration; + + if (PciDevicePath == NULL || GopDevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize the GopDevicePath to be PciDevicePath + // + *GopDevicePath = PciDevicePath; + TempPciDevicePath = PciDevicePath; + + Status = gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &TempPciDevicePath, + &PciDeviceHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Try to connect this handle, 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. + // + + // + // Select display devices + // + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + L"Setup", + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &mSystemConfiguration + ); + ASSERT_EFI_ERROR (Status); + + if(mSystemConfiguration.BootDisplayDevice != 0x0) + { + ACPI_ADR_DEVICE_PATH AcpiAdr; + EFI_DEVICE_PATH_PROTOCOL *MyDevicePath = NULL; + + AcpiAdr.Header.Type = ACPI_DEVICE_PATH; + AcpiAdr.Header.SubType = ACPI_ADR_DP; + + switch (mSystemConfiguration.BootDisplayDevice) { + case 1: + AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, PORT_CRT, 0); //CRT Device + break; + case 2: + AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, PORT_B_HDMI, 0); //HDMI Device Port B + break; + case 3: + AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, PORT_B_DP, 0); //DP PortB + break; + case 4: + AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, PORT_C_DP, 0); //DP PortC + break; + case 5: + AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, PORT_C_DP, 0); //eDP Port C + break; + case 6: + AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, PORT_MIPI_A, 0); //DSI Port A + break; + case 7: + AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, PORT_MIPI_C, 0); //DSI Port C + break; + default: + AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, PORT_CRT, 0); + break; + } + + SetDevicePathNodeLength (&AcpiAdr.Header, sizeof (ACPI_ADR_DEVICE_PATH)); + + MyDevicePath = AppendDevicePathNode(MyDevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&AcpiAdr); + + gBS->ConnectController ( + PciDeviceHandle, + NULL, + MyDevicePath, + FALSE + ); + + FreePool(MyDevicePath); + } + else + { + gBS->ConnectController ( + PciDeviceHandle, + NULL, + NULL, + FALSE + ); + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiGraphicsOutputProtocolGuid, + NULL, + &GopHandleCount, + &GopHandleBuffer + ); + if (!EFI_ERROR (Status)) { + // + // Add all the child handles as possible Console Device + // + for (Index = 0; Index < GopHandleCount; Index++) { + Status = gBS->HandleProtocol ( + GopHandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + (VOID**)&TempDevicePath + ); + if (EFI_ERROR (Status)) { + continue; + } + if (CompareMem ( + PciDevicePath, + TempDevicePath, + GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH + ) == 0) { + // + // In current implementation, we only enable one of the child handles + // as console device, i.e. sotre one of the child handle's device + // path to variable "ConOut" + // In futhure, we could select all child handles to be console device + // + *GopDevicePath = TempDevicePath; + } + } + gBS->FreePool (GopHandleBuffer); + } + + return EFI_SUCCESS; +} + +/** + + Search out all the platform pci or agp video device. The function may will + find multiple video device, and return all enabled device path. + + @param PlugInPciVgaDevicePath Return the platform plug in pci video device + path if the system have plug in pci video device. + @param OnboardPciVgaDevicePath Return the platform active agp video device path + if the system have plug in agp video device or on + chip agp device. + + @retval EFI_SUCCSS Get all platform active video device path. + @retval EFI_STATUS Return the status of gBS->LocateDevicePath (), + gBS->ConnectController (), + and gBS->LocateHandleBuffer (). + +**/ +EFI_STATUS +GetPlugInPciVgaDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **PlugInPciVgaDevicePath, + IN OUT EFI_DEVICE_PATH_PROTOCOL **OnboardPciVgaDevicePath + ) +{ + EFI_STATUS Status; + EFI_HANDLE RootHandle; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + UINTN Index1; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BOOLEAN PlugInPciVga; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + DevicePath = NULL; + PlugInPciVga = TRUE; + HandleCount = 0; + HandleBuffer = NULL; + + // + // Make all the PCI_IO protocols on PCI Seg 0 show up + // + BdsLibConnectDevicePath (gPlatformRootBridges[0]); + + Status = gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &gPlatformRootBridges[0], + &RootHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->ConnectController ( + RootHandle, + NULL, + NULL, + FALSE + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Start to check all the pci io to find all possible VGA device + // + HandleCount = 0; + HandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID**)&PciIo + ); + if (!EFI_ERROR (Status)) { + + // + // Check for all VGA device + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Here we decide which VGA device to enable in PCI bus + // + // The first plugin PCI VGA card device will be present as PCI VGA + // The onchip AGP or AGP card will be present as AGP VGA + // + if (!IS_PCI_VGA (&Pci)) { + continue; + } + + // + // Set the device as the possible console out device, + // + // Below code will make every VGA device to be one + // of the possibe console out device + // + PlugInPciVga = TRUE; + gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + (VOID**)&DevicePath + ); + + Index1 = 0; + + while (gPlatformAllPossiblePciVgaConsole[Index1] != NULL) { + if (CompareMem ( + DevicePath, + gPlatformAllPossiblePciVgaConsole[Index1], + GetDevicePathSize (gPlatformAllPossiblePciVgaConsole[Index1]) + ) == 0) { + + // + // This device is an AGP device + // + *OnboardPciVgaDevicePath = DevicePath; + PlugInPciVga = FALSE; + break; + } + + Index1 ++; + } + + if (PlugInPciVga) { + *PlugInPciVgaDevicePath = DevicePath; + } + } + } + + FreePool (HandleBuffer); + + return EFI_SUCCESS; +} + +/** + + Find the platform active vga, and base on the policy to enable the vga as + the console out device. The policy is driven by one setup variable "VBIOS". + + None. + + @param EFI_UNSUPPORTED There is no active vga device + + @retval EFI_STATUS Return the status of BdsLibGetVariableAndSize () + +**/ +EFI_STATUS +PlatformBdsForceActiveVga ( + VOID + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *PlugInPciVgaDevicePath; + EFI_DEVICE_PATH_PROTOCOL *OnboardPciVgaDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathFirst; + EFI_DEVICE_PATH_PROTOCOL *DevicePathSecond; + EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; + UINTN VarSize; + SYSTEM_CONFIGURATION mSystemConfiguration; + + Status = EFI_SUCCESS; + PlugInPciVgaDevicePath = NULL; + OnboardPciVgaDevicePath = NULL; + + // + // Check the policy which is the first enabled VGA + // + GetPlugInPciVgaDevicePath (&PlugInPciVgaDevicePath, &OnboardPciVgaDevicePath); + + if (PlugInPciVgaDevicePath == NULL && OnboardPciVgaDevicePath == NULL) { + return EFI_UNSUPPORTED; + } + + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + L"Setup", + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &mSystemConfiguration + ); + ASSERT_EFI_ERROR (Status); + + + if ((PlugInPciVgaDevicePath == NULL && OnboardPciVgaDevicePath != NULL) ) { + DEBUG ((EFI_D_ERROR,"Update onboard PCI VGA ...\n")); + DevicePathFirst = OnboardPciVgaDevicePath; + DevicePathSecond = PlugInPciVgaDevicePath; + goto UpdateConOut; + } + if(OnboardPciVgaDevicePath != NULL && mSystemConfiguration.PrimaryVideoAdaptor == 0) { + DEBUG ((EFI_D_ERROR,"Update onboard PCI VGA When set primary!!!...\n")); + DevicePathFirst = OnboardPciVgaDevicePath; + DevicePathSecond = PlugInPciVgaDevicePath; + goto UpdateConOut; + } + + DEBUG ((EFI_D_ERROR,"Update plug in PCI VGA ...\n")); + DevicePathFirst = PlugInPciVgaDevicePath; + DevicePathSecond = OnboardPciVgaDevicePath; + +UpdateConOut: + GetGopDevicePath (DevicePathFirst, &GopDevicePath); + DevicePathFirst = GopDevicePath; + + Status = BdsLibUpdateConsoleVariable ( + L"ConOut", + DevicePathFirst, + DevicePathSecond + ); + + return Status; +} + +VOID +UpdateConsoleResolution( + VOID + ) +{ + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + SYSTEM_CONFIGURATION SystemConfiguration; + UINTN VarSize; + EFI_STATUS Status; + + + HorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution); + VerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution); + + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + L"Setup", + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &SystemConfiguration + ); + ASSERT_EFI_ERROR (Status); + + switch (SystemConfiguration.IgdFlatPanel) { + + case 0: + // + // Use the detault PCD values. + // + break; + + case 1: + HorizontalResolution = 640; + VerticalResolution = 480; + break; + + case 2: + HorizontalResolution = 800; + VerticalResolution = 600; + break; + + case 3: + HorizontalResolution = 1024; + VerticalResolution = 768; + break; + + case 4: + HorizontalResolution = 1280; + VerticalResolution = 1024; + break; + + case 5: + HorizontalResolution = 1366; + VerticalResolution = 768; + break; + + case 6: + HorizontalResolution = 1680; + VerticalResolution = 1050; + break; + + case 7: + HorizontalResolution = 1920; + VerticalResolution = 1200; + break; + + case 8: + HorizontalResolution = 1280; + VerticalResolution = 800; + break; + } + + PcdSet32 (PcdSetupVideoHorizontalResolution, HorizontalResolution); + PcdSet32 (PcdSetupVideoVerticalResolution, VerticalResolution); + DEBUG ((EFI_D_ERROR, "HorizontalResolution = %x; VerticalResolution = %x", HorizontalResolution, VerticalResolution)); + + return; +} + +/** + Connect the predefined platform default console device. Always try to find + and enable the vga device if have. + + @param PlatformConsole Predfined platform default console device array. + + @retval EFI_SUCCESS Success connect at least one ConIn and ConOut + device, there must have one ConOut device is + active vga device. + + @retval EFI_STATUS Return the status of + BdsLibConnectAllDefaultConsoles () + +**/ +EFI_STATUS +PlatformBdsConnectConsole ( + IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole +) +{ + EFI_STATUS Status; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *VarConout; + EFI_DEVICE_PATH_PROTOCOL *VarConin; + UINTN DevicePathSize; + + UpdateConsoleResolution(); + + Index = 0; + Status = EFI_SUCCESS; + DevicePathSize = 0; + VarConout = BdsLibGetVariableAndSize ( + L"ConOut", + &gEfiGlobalVariableGuid, + &DevicePathSize + ); + VarConin = BdsLibGetVariableAndSize ( + L"ConIn", + &gEfiGlobalVariableGuid, + &DevicePathSize + ); + if (VarConout == NULL || VarConin == NULL) { + // + // Have chance to connect the platform default console, + // the platform default console is the minimue device group + // the platform should support + // + while (PlatformConsole[Index].DevicePath != NULL) { + + // + // Update the console variable with the connect type + // + if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { + BdsLibUpdateConsoleVariable (L"ConIn", PlatformConsole[Index].DevicePath, NULL); + } + + if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { + BdsLibUpdateConsoleVariable (L"ConOut", PlatformConsole[Index].DevicePath, NULL); + } + + if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { + BdsLibUpdateConsoleVariable (L"ErrOut", PlatformConsole[Index].DevicePath, NULL); + } + + Index ++; + } + } + + // + // Make sure we have at least one active VGA, and have the right + // active VGA in console variable + // + Status = PlatformBdsForceActiveVga (); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((EFI_D_INFO, "DISPLAY INIT DONE\n")); + + // + // Connect the all the default console with current console variable + // + Status = BdsLibConnectAllDefaultConsoles (); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Connect with predeined platform connect sequence, + the OEM/IBV can customize with their own connect sequence. + + @param None. + + @retval None. + +**/ +VOID +PlatformBdsConnectSequence ( + VOID + ) +{ + UINTN Index; + + Index = 0; + + // + // 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 + // + while (gPlatformConnectSequence[Index] != NULL) { + + // + // Build the platform boot option + // + BdsLibConnectDevicePath (gPlatformConnectSequence[Index]); + Index ++; + } + + // + // Just use the simple policy to connect all devices + // There should be no difference between debug tip and release tip, or it will be extremely hard to debug. + // + // There is case that IdeController driver will write boot script in driver model Start() function. It will be rejected by boot script save. + // It is only found when DEBUG disabled, because we are using BdsLibConnectAll() when DEBUG enabled. + // + // So we use BdsLibConnectAll() here to make sure IdeController.Start() is invoked before InstallReadyToLock(). + // We may also consider to connect SataController only later if needed. + // + BdsLibConnectAll (); +} + +/** + + Load the predefined driver option, OEM/IBV can customize this + to load their own drivers + + @param BdsDriverLists The header of the driver option link list. + + @retval None. + +**/ +VOID +PlatformBdsGetDriverOption ( + IN OUT LIST_ENTRY *BdsDriverLists + ) +{ + UINTN Index; + + Index = 0; + + // + // Here we can get the customized platform driver option + // + while (gPlatformDriverOption[Index] != NULL) { + + // + // Build the platform boot option + // + BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder"); + Index ++; + } + +} + +/** + This function is used for some critical time if the the system + have no any boot option, and there is no time out for user to add + the new boot option. This can also treat as the platform default + boot option. + + @param BdsBootOptionList The header of the boot option link list. + + @retval None. + +**/ +VOID +PlatformBdsPredictBootOption ( + IN OUT LIST_ENTRY *BdsBootOptionList + ) +{ + UINTN Index; + + Index = 0; + + // + // Here give chance to get platform boot option data + // + while (gPlatformBootOption[Index] != NULL) { + + // + // Build the platform boot option + // + BdsLibRegisterNewOption (BdsBootOptionList, gPlatformBootOption[Index], NULL, L"BootOrder"); + Index ++; + } +} + +/** + Perform the platform diagnostic, such like test memory. OEM/IBV also + can customize this fuction to support specific platform diagnostic. + + @param MemoryTestLevel The memory test intensive level + @param QuietBoot Indicate if need to enable the quiet boot + @param BaseMemoryTest A pointer to BdsMemoryTest() + + @retval None. + +**/ +VOID +PlatformBdsDiagnostics ( + IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel, + IN BOOLEAN QuietBoot, + IN BASEM_MEMORY_TEST BaseMemoryTest + ) +{ + 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 = BaseMemoryTest (MemoryTestLevel); + if (EFI_ERROR (Status)) { + DisableQuietBoot (); + } + + return; + } + + // + // Perform system diagnostic + // + Status = BaseMemoryTest (MemoryTestLevel); +} + + +/** + + 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. + + @param DriverOptionList - The header of the driver option link list + @param BootOptionList - The header of the boot option link list + @param ProcessCapsules - A pointer to ProcessCapsules() + @param BaseMemoryTest - A pointer to BaseMemoryTest() + + @retval None. + +**/ +VOID +EFIAPI +PlatformBdsPolicyBehavior ( + IN OUT LIST_ENTRY *DriverOptionList, + IN OUT LIST_ENTRY *BootOptionList, + IN PROCESS_CAPSULES ProcessCapsules, + IN BASEM_MEMORY_TEST BaseMemoryTest + ) +{ + EFI_STATUS Status; + UINT16 Timeout; + EFI_BOOT_MODE BootMode; + BOOLEAN DeferredImageExist; + UINTN Index; + CHAR16 CapsuleVarName[36]; + CHAR16 *TempVarName; + SYSTEM_CONFIGURATION SystemConfiguration; + UINTN VarSize; + BOOLEAN SetVariableFlag; + PLATFORM_PCI_DEVICE_PATH *EmmcBootDevPath; + EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea; + EFI_HANDLE FvProtocolHandle; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index1; + UINTN SataPciRegBase = 0; + UINT16 SataModeSelect = 0; + VOID *RegistrationExitPmAuth = NULL; + EFI_EVENT Event; + BOOLEAN IsFirstBoot; + UINT16 *BootOrder; + UINTN BootOrderSize; + + Timeout = PcdGet16 (PcdPlatformBootTimeOut); + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + NORMAL_SETUP_NAME, + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &SystemConfiguration + ); + if (EFI_ERROR (Status)) { + return; + } + + // + // Load the driver option as the driver option list + // + PlatformBdsGetDriverOption (DriverOptionList); + + // + // Get current Boot Mode + // + BootMode = GetBootModeHob(); + + // + // 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; + SetVariableFlag = TRUE; + while (SetVariableFlag) { + 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 + // + SetVariableFlag = FALSE; + continue; + } + Index++; + } + + // + // No deferred images exist by default + // + DeferredImageExist = FALSE; + if ((BootMode != BOOT_WITH_MINIMAL_CONFIGURATION) && (PcdGet32(PcdFlashFvShellSize) > 0)){ + gDS->ProcessFirmwareVolume ( + (VOID *)(UINTN)PcdGet32(PcdFlashFvShellBase), + PcdGet32(PcdFlashFvShellSize), + &FvProtocolHandle + ); + } + + if (SystemConfiguration.FastBoot == 1) { + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + if ((BootOrder != NULL) && (BootMode != BOOT_ON_FLASH_UPDATE)) { + // + // BootOrder exist, it means system has boot before. We can do fast boot. + // + BootMode = BOOT_WITH_MINIMAL_CONFIGURATION; + } + } + + + // + // Use eMMC to boot OS and turn on AHCI, when SATA HDD is diconnected, + // SATA AHCI CTLR device will show yellow bang, implement this solution to solve it. + // + SataPciRegBase = MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_SATA, 0, 0); + SataModeSelect = MmioRead16 (SataPciRegBase + R_PCH_SATA_MAP) & B_PCH_SATA_MAP_SMS_MASK; + Status = EFI_SUCCESS; + if (SataModeSelect != V_PCH_SATA_MAP_SMS_IDE) { + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + DisableAhciCtlr, + &SataPciRegBase, + &Event + ); + if (!EFI_ERROR (Status)) { + Status = gBS->RegisterProtocolNotify ( + &gExitPmAuthProtocolGuid, + Event, + &RegistrationExitPmAuth + ); + } + } + + switch (BootMode) { + + case BOOT_WITH_MINIMAL_CONFIGURATION: + PlatformBdsInitHotKeyEvent (); + PlatformBdsConnectSimpleConsole (gPlatformSimpleConsole); + + + // + // Check to see if it's needed to dispatch more DXE drivers. + // + for (Index = 0; Index < sizeof(ConnectDriverTable)/sizeof(EFI_GUID *); Index++) { + Status = gBS->LocateHandleBuffer ( + ByProtocol, + ConnectDriverTable[Index], + NULL, + &HandleCount, + &HandleBuffer + ); + if (!EFI_ERROR (Status)) { + for (Index1 = 0; Index1 < HandleCount; Index1++) { + gBS->ConnectController ( + HandleBuffer[Index1], + NULL, + NULL, + TRUE + ); + } + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + gDS->Dispatch (); + } + + // + // Locate the Global NVS Protocol. + // + Status = gBS->LocateProtocol ( + &gEfiGlobalNvsAreaProtocolGuid, + NULL, + (void **)&GlobalNvsArea + ); + if (GlobalNvsArea->Area->emmcVersion == 0){ + EmmcBootDevPath = (PLATFORM_PCI_DEVICE_PATH *)gPlatformSimpleBootOption[0]; + EmmcBootDevPath->PciDevice.Device = 0x10; + } + + // + // Connect boot device here to give time to read keyboard. + // + BdsLibConnectDevicePath (gPlatformSimpleBootOption[0]); + + // + // This is a workround for dectecting hotkey from USB keyboard. + // + gBS->Stall(KEYBOARD_TIMER_INTERVAL); + + if (mHotKeyTimerEvent != NULL) { + gBS->SetTimer ( + mHotKeyTimerEvent, + TimerCancel, + 0 + ); + gBS->CloseEvent (mHotKeyTimerEvent); + mHotKeyTimerEvent = NULL; + } + if (mHotKeyPressed) { + // + // Skip show progress count down + // + Timeout = 0xFFFF; + goto FULL_CONFIGURATION; + } + + if (SystemConfiguration.QuietBoot) { + EnableQuietBoot (PcdGetPtr(PcdLogoFile)); + } else { + PlatformBdsDiagnostics (IGNORE, FALSE, BaseMemoryTest); + } + + +#ifdef TPM_ENABLED + TcgPhysicalPresenceLibProcessRequest(); +#endif + + // + // Close boot script and install ready to lock + // + InstallReadyToLock (); + + // + // Give one chance to enter the setup if we + // select Gummiboot "Reboot Into Firmware Interface" and Fast Boot is enabled. + // + BootIntoFirmwareInterface(); + break; + + case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES: + + // + // In no-configuration boot mode, we can connect the + // console directly. + // + BdsLibConnectAllDefaultConsoles (); + PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest); + + // + // Perform some platform specific connect sequence + // + PlatformBdsConnectSequence (); + + // + // As console is ready, perform user identification again. + // + if (mCurrentUser == NULL) { + PlatformBdsUserIdentify (&mCurrentUser, &DeferredImageExist); + if (DeferredImageExist) { + // + // After user authentication, the deferred drivers was loaded again. + // Here, need to ensure the deferred images are connected. + // + BdsLibConnectAllDefaultConsoles (); + PlatformBdsConnectSequence (); + } + } + + // + // Close boot script and install ready to lock + // + InstallReadyToLock (); + + // + // Notes: current time out = 0 can not enter the + // front page + // + PlatformBdsEnterFrontPageWithHotKey (Timeout, FALSE); + + // + // Check the boot option with the boot option list + // + BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); + break; + + case BOOT_ON_FLASH_UPDATE: + + // + // Boot with the specific configuration + // + PlatformBdsConnectConsole (gPlatformConsole); + PlatformBdsDiagnostics (EXTENSIVE, FALSE, BaseMemoryTest); + BdsLibConnectAll (); + + // + // Perform user identification + // + if (mCurrentUser == NULL) { + PlatformBdsUserIdentify (&mCurrentUser, &DeferredImageExist); + if (DeferredImageExist) { + // + // After user authentication, the deferred drivers was loaded again. + // Here, need to ensure the deferred images are connected. + // + BdsLibConnectAll (); + } + } + + // + // Close boot script and install ready to lock + // + InstallReadyToLock (); + + ProcessCapsules (BOOT_ON_FLASH_UPDATE); + break; + + case BOOT_IN_RECOVERY_MODE: + + // + // In recovery mode, just connect platform console + // and show up the front page + // + PlatformBdsConnectConsole (gPlatformConsole); + PlatformBdsDiagnostics (EXTENSIVE, FALSE, BaseMemoryTest); + BdsLibConnectAll (); + + // + // Perform user identification + // + if (mCurrentUser == NULL) { + PlatformBdsUserIdentify (&mCurrentUser, &DeferredImageExist); + if (DeferredImageExist) { + // + // After user authentication, the deferred drivers was loaded again. + // Here, need to ensure the deferred drivers are connected. + // + BdsLibConnectAll (); + } + } + + // + // Close boot script and install ready to lock + // + InstallReadyToLock (); + + // + // In recovery boot mode, we still enter to the + // frong page now + // + PlatformBdsEnterFrontPageWithHotKey (Timeout, FALSE); + break; + +FULL_CONFIGURATION: + case BOOT_WITH_FULL_CONFIGURATION: + case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS: + case BOOT_WITH_DEFAULT_SETTINGS: + default: + + // + // Connect platform console + // + Status = PlatformBdsConnectConsole (gPlatformConsole); + if (EFI_ERROR (Status)) { + + // + // Here OEM/IBV can customize with defined action + // + PlatformBdsNoConsoleAction (); + } + + // + // Chenyunh[TODO]: This is Workgroud to show the fs for uSDcard, + // Need to root cause this issue. + // + DEBUG ((DEBUG_ERROR, "Start to reconnect all driver.\n")); + BdsLibDisconnectAllEfi(); + BdsLibConnectAll (); + DEBUG ((DEBUG_ERROR, "End to reconnect all driver.\n")); + + // + // Perform some platform specific connect sequence + // + PlatformBdsConnectSequence (); + if (SystemConfiguration.QuietBoot) { + EnableQuietBoot (PcdGetPtr(PcdLogoFile)); + } else { + PlatformBdsDiagnostics (IGNORE, FALSE, BaseMemoryTest); + } + + // + // Do a pre-delay so Hard Disk can spin up and see more logo. + // + gBS->Stall(SystemConfiguration.HddPredelay * 1000000); + + // + // Perform user identification + // + if (mCurrentUser == NULL) { + PlatformBdsUserIdentify (&mCurrentUser, &DeferredImageExist); + if (DeferredImageExist) { + // + // After user authentication, the deferred drivers was loaded again. + // Here, need to ensure the deferred drivers are connected. + // + Status = PlatformBdsConnectConsole (gPlatformConsole); + if (EFI_ERROR (Status)) { + PlatformBdsNoConsoleAction (); + } + PlatformBdsConnectSequence (); + } + } +#ifdef TPM_ENABLED + TcgPhysicalPresenceLibProcessRequest(); +#endif + + // + // Close boot script and install ready to lock + // + InstallReadyToLock (); + + // + // Give one chance to enter the setup if we + // have the time out + // + PlatformBdsEnterFrontPageWithHotKey (Timeout, FALSE); + + // + // Give one chance to enter the setup if we + // select Gummiboot "Reboot Into Firmware Interface" + // + BootIntoFirmwareInterface(); + + // + // In default boot mode, always find all boot + // option and do enumerate all the default boot option + // + if (Timeout == 0) { + BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); + if (IsListEmpty(BootOptionList)) { + PlatformBdsPredictBootOption (BootOptionList); + } + + return; + } + + // + // Here we have enough time to do the enumeration of boot device + // + BdsLibEnumerateAllBootOption (BootOptionList); + break; + } + + + IsFirstBoot = PcdGetBool(PcdBootState); + if (IsFirstBoot) { + PcdSetBool(PcdBootState, FALSE); + } + return; + +} + +/** + Hook point after a boot attempt succeeds. We don't expect a boot option to + return, so the UEFI 2.0 specification defines that you will default to an + interactive mode and stop processing the BootOrder list in this case. This + is alos a platform implementation and can be customized by IBV/OEM. + + @param Option Pointer to Boot Option that succeeded to boot. + + @retval None. + +**/ +VOID +EFIAPI +PlatformBdsBootSuccess ( + IN BDS_COMMON_OPTION *Option + ) +{ + CHAR16 *TmpStr; + + // + // If Boot returned with EFI_SUCCESS and there is not in the boot device + // select loop then we need to pop up a UI and wait for user input. + // + TmpStr = Option->StatusString; + if (TmpStr != NULL) { + BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); + FreePool(TmpStr); + } +} + +/** + Hook point after a boot attempt fails. + + @param Option - Pointer to Boot Option that failed to boot. + @param Status - Status returned from failed boot. + @param ExitData - Exit data returned from failed boot. + @param ExitDataSize - Exit data size returned from failed boot. + + @retval None. + +**/ +VOID +EFIAPI +PlatformBdsBootFail ( + IN BDS_COMMON_OPTION *Option, + IN EFI_STATUS Status, + IN CHAR16 *ExitData, + IN UINTN ExitDataSize + ) +{ + CHAR16 *TmpStr; + EFI_HANDLE FvProtocolHandle; + + // + // If Boot returned with failed status then we need to pop up a UI and wait + // for user input. + // + TmpStr = Option->StatusString; + if (TmpStr != NULL) { + BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); + FreePool(TmpStr); + } + if (PcdGet32(PcdFlashFvShellSize) > 0){ + gDS->ProcessFirmwareVolume ( + (VOID *)(UINTN)PcdGet32(PcdFlashFvShellBase), + PcdGet32(PcdFlashFvShellSize), + &FvProtocolHandle + ); + } + PlatformBdsConnectSequence (); +} + +/** + This function is remained for IBV/OEM to do some platform action, + if there no console device can be connected. + + @param None. + + @retval EFI_SUCCESS Direct return success now. + +**/ +EFI_STATUS +PlatformBdsNoConsoleAction ( + VOID + ) +{ + return EFI_SUCCESS; +} + +/** + This function locks the block + + @param Base The base address flash region to be locked. + +**/ +VOID +BdsLockFv ( + IN EFI_PHYSICAL_ADDRESS Base + ) +{ + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT8 Data; + UINT32 BlockLength; + UINTN Index; + + BaseAddress = Base - 0x400000 + 2; + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (Base)); + BlockMap = &(FvHeader->BlockMap[0]); + + while ((BlockMap->NumBlocks != 0) && (BlockMap->Length != 0)) { + BlockLength = BlockMap->Length; + for (Index = 0; Index < BlockMap->NumBlocks; Index++) { + Data = MmioOr8 ((UINTN) BaseAddress, 0x03); + BaseAddress += BlockLength; + } + BlockMap++; + } +} + +VOID +EFIAPI +PlatformBdsLockNonUpdatableFlash ( + VOID + ) +{ + EFI_PHYSICAL_ADDRESS Base; + + Base = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashFvMainBase); + if (Base > 0) { + BdsLockFv (Base); + } + + Base = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashFvRecoveryBase); + if (Base > 0) { + BdsLockFv (Base); + } +} + +/** + Lock the ConsoleIn device in system table. All key + presses will be ignored until the Password is typed in. The only way to + disable the password is to type it in to a ConIn device. + + @param Password Password used to lock ConIn device. + + @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully. + @retval EFI_UNSUPPORTED Password not found + +**/ +EFI_STATUS +EFIAPI +LockKeyboards ( + IN CHAR16 *Password + ) +{ + return EFI_UNSUPPORTED; +} + +/** + 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 +PlatformBdsConnectAuthDevice ( + 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 + // + BdsLibConnectDevicePath (gUserAuthenticationDevice[Index]); + 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 +EFIAPI +PlatformBdsUserIdentify ( + 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 = BdsLibUserIdentify (User); + } while (EFI_ERROR (Status)); + + // + // After user authentication now, try to find whether deferred image 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); +} + +UINTN gHotKey = 0; + + +EFI_STATUS +ShowProgressHotKey ( + IN UINT16 TimeoutDefault + ) +{ + CHAR16 *TmpStr; + UINT16 TimeoutRemain; + EFI_STATUS Status; + EFI_INPUT_KEY Key; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; + UINT32 GpioValue; + + if (TimeoutDefault == 0) { + return EFI_TIMEOUT; + } + + if (DebugAssertEnabled()) + { + DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it, or press or to enter setup page! ...Zzz....\n")); + } + else + { + #ifdef __GNUC__ + SerialPortWrite((UINT8 *)"\n\n>>>>Start boot option, Press or to enter setup page(5 Sec)[GCC]", 76); + #else + SerialPortWrite((UINT8 *)"\n\n>>>>Start boot option, Press or to enter setup page(5 Sec)", 71); + #endif + } + 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); + + // + // Clear the progress status bar first + // + TmpStr = L"Start boot option, Press or to enter setup page."; + PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0); + + TimeoutRemain = TimeoutDefault; + while (TimeoutRemain != 0) { + if (DebugAssertEnabled()) + { + DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain)); + } + else + { + SerialPortWrite ((UINT8 *)".", 1); + } + Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND); + if (Status != EFI_TIMEOUT) { + break; + } + TimeoutRemain--; + + // + // Show progress + // + if (TmpStr != NULL) { + PlatformBdsShowProgress ( + Foreground, + Background, + TmpStr, + Color, + ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault), + 0 + ); + } + } + + // + // Timeout expired + // + if (TimeoutRemain == 0) { + if (DebugAssertEnabled()) + { + } + else + { + SerialPortWrite ((UINT8 *)"\r\n", 2); + } + return EFI_TIMEOUT; + } + + // + // User pressed some key + // + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check Volume Up Key to enter Setup + // + GpioValue = MmioRead32 (IO_BASE_ADDRESS + 0x0668); // The value of GPIOC_5 + if (((GpioValue & BIT0) == 0) && (Key.ScanCode == SCAN_UP)) { + gHotKey = 0; + return EFI_SUCCESS; + } + + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + // + // User pressed enter, equivalent to select "continue" + // + return EFI_TIMEOUT; + } + + // + //F2 -- Front Page + //F5 -- Device Manager + //F7 -- Boot Manager + // do not use F8. generally people assume it is windows safe mode key. + //F9 -- Boot order + // + DEBUG ((EFI_D_INFO, "[Key Pressed]: ScanCode 0x%x\n", Key.ScanCode)); + switch(Key.ScanCode) { + case SCAN_F2: + gHotKey = 0; + break; + + case SCAN_DELETE: + gHotKey = 0; + break; + + case SCAN_F5: + gHotKey = FRONT_PAGE_KEY_DEVICE_MANAGER; + break; + + case SCAN_F7: + gHotKey = FRONT_PAGE_KEY_BOOT_MANAGER; + break; + + case SCAN_F9: + gHotKey = FRONT_PAGE_KEY_BOOT_MAINTAIN; + break; + + default: + //set gHotKey to continue so that flow will not go into CallFrontPage + gHotKey = FRONT_PAGE_KEY_CONTINUE; + return EFI_TIMEOUT; + break; + } + + return EFI_SUCCESS; +} + + + +/** + This function is the main entry of the platform setup entry. + The function will present the main menu of the system setup, + this is the platform reference part and can be customize. + + + @param TimeoutDefault The fault time out value before the system + continue to boot. + @param ConnectAllHappened The indicater to check if the connect all have + already happened. + +**/ +VOID +PlatformBdsEnterFrontPageWithHotKey ( + IN UINT16 TimeoutDefault, + IN BOOLEAN ConnectAllHappened + ) +{ + EFI_STATUS Status; + + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; + UINTN BootTextColumn; + UINTN BootTextRow; + + GraphicsOutput = NULL; + SimpleTextOut = NULL; + + PERF_START (NULL, "BdsTimeOut", "BDS", 0); + + // + // Indicate if we need connect all in the platform setup + // + if (ConnectAllHappened) { + gConnectAllHappened = TRUE; + } + + if (!mModeInitialized) { + // + // After the console is ready, get current video resolution + // and text mode before launching setup at first time. + // + Status = gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID**)&GraphicsOutput + ); + if (EFI_ERROR (Status)) { + GraphicsOutput = NULL; + } + + Status = gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID**)&SimpleTextOut + ); + if (EFI_ERROR (Status)) { + SimpleTextOut = NULL; + } + + if (GraphicsOutput != NULL) { + // + // Get current video resolution and text mode. + // + mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution; + mBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution; + } + + if (SimpleTextOut != NULL) { + Status = SimpleTextOut->QueryMode ( + SimpleTextOut, + SimpleTextOut->Mode->Mode, + &BootTextColumn, + &BootTextRow + ); + mBootTextModeColumn = (UINT32)BootTextColumn; + mBootTextModeRow = (UINT32)BootTextRow; + } + + // + // Get user defined text mode for setup. + // + mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution); + mSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution); + mSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn); + mSetupTextModeRow = PcdGet32 (PcdSetupConOutRow); + + mModeInitialized = TRUE; + } + + if (TimeoutDefault != 0xffff) { + Status = ShowProgressHotKey (TimeoutDefault); + + // + // Ensure screen is clear when switch Console from Graphics mode to Text mode + // + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + gST->ConOut->ClearScreen (gST->ConOut); + + if (EFI_ERROR (Status)) { + // + // Timeout or user press enter to continue + // + goto Exit; + } + } + + do { + + BdsSetConsoleMode (TRUE); + + InitializeFrontPage (FALSE); + + // + // Update Front Page strings + // + UpdateFrontPageStrings (); + + Status = EFI_SUCCESS; + gCallbackKey = 0; + if (gHotKey == 0) { + Status = CallFrontPage (); + } else { + gCallbackKey = gHotKey; + gHotKey = 0; + } + + // + // If gCallbackKey is greater than 1 and less or equal to 5, + // it will launch configuration utilities. + // 2 = set language + // 3 = boot manager + // 4 = device manager + // 5 = boot maintenance manager + // + if (gCallbackKey != 0) { + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP) + ); + } + + // + // Based on the key that was set, we can determine what to do + // + switch (gCallbackKey) { + // + // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can + // describe to their customers in documentation how to find their setup information (namely + // under the device manager and specific buckets) + // + // These entries consist of the Continue, Select language, Boot Manager, and Device Manager + // + case FRONT_PAGE_KEY_CONTINUE: + + // + // User hit continue + // + break; + + case FRONT_PAGE_KEY_LANGUAGE: + + // + // User made a language setting change - display front page again + // + break; + + case FRONT_PAGE_KEY_BOOT_MANAGER: + + // + // User chose to run the Boot Manager + // + CallBootManager (); + break; + + case FRONT_PAGE_KEY_DEVICE_MANAGER: + + // + // Display the Device Manager + // + do { + CallDeviceManager (); + } while (gCallbackKey == FRONT_PAGE_KEY_DEVICE_MANAGER); + break; + + case FRONT_PAGE_KEY_BOOT_MAINTAIN: + + // + // Display the Boot Maintenance Manager + // + BdsStartBootMaint (); + break; + } + + } while (((UINTN)gCallbackKey) != FRONT_PAGE_KEY_CONTINUE); + + // + //Will leave browser, check any reset required change is applied? if yes, reset system + // + SetupResetReminder (); + +Exit: + // + // Automatically load current entry + // Note: The following lines of code only execute when Auto boot + // takes affect + // + PERF_END (NULL, "BdsTimeOut", "BDS", 0); +} + + +VOID +BootIntoFirmwareInterface( +VOID +) +{ + EFI_STATUS Status; + UINTN DataSize; + UINT16 Timeout; + UINT64 OsIndication; + + + OsIndication = 0; + DataSize = sizeof(UINT64); + Status = gRT->GetVariable ( + L"OsIndications", + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + &OsIndication + ); + + DEBUG ((EFI_D_INFO, "OSIndication Variable Value %d\n", OsIndication)); + // + //Goto FrontPage directly when bit EFI_OS_INDICATIONS_BOOT_TO_FW_UI in OSIndication Variable is setted. + // + if (!EFI_ERROR(Status) && (OsIndication != 0)) { + Timeout = 0xffff; + PlatformBdsEnterFrontPage (Timeout, FALSE); + } +} + + +EFI_STATUS +PlatformBdsConnectSimpleConsole ( + IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole +) +{ + EFI_STATUS Status; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *VarConout; + EFI_DEVICE_PATH_PROTOCOL *VarConin; + UINTN DevicePathSize; + + + Index = 0; + Status = EFI_SUCCESS; + DevicePathSize = 0; + VarConout = BdsLibGetVariableAndSize ( + L"ConOut", + &gEfiGlobalVariableGuid, + &DevicePathSize + ); + VarConin = BdsLibGetVariableAndSize ( + L"ConIn", + &gEfiGlobalVariableGuid, + &DevicePathSize + ); + if (VarConout == NULL || VarConin == NULL) { + // + // Have chance to connect the platform default console, + // the platform default console is the minimue device group + // the platform should support + // + while (PlatformConsole[Index].DevicePath != NULL) { + + // + // Update the console variable with the connect type + // + if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { + BdsLibUpdateConsoleVariable (L"ConIn", PlatformConsole[Index].DevicePath, NULL); + } + + if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { + BdsLibUpdateConsoleVariable (L"ConOut", PlatformConsole[Index].DevicePath, NULL); + } + + if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { + BdsLibUpdateConsoleVariable (L"ErrOut", PlatformConsole[Index].DevicePath, NULL); + } + + Index ++; + } + } + + // + // Connect ConIn first to give keyboard time to parse hot key event. + // + Status = BdsLibConnectConsoleVariable (L"ConIn"); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Make sure we have at least one active VGA, and have the right + // active VGA in console variable + // + Status = PlatformBdsForceActiveVga (); + + // + // It seems impossible not to have any ConOut device on platform, + // so we check the status here. + // + Status = BdsLibConnectConsoleVariable (L"ConOut"); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +/** + Timer handler to convert the key from USB. + + @param Event Indicates the event that invoke this function. + @param Context Indicates the calling context. +**/ +VOID +EFIAPI +HotKeyTimerHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR (Status)) { + return; + } + + switch(Key.ScanCode) { + case SCAN_F2: + gHotKey = 0; + mHotKeyPressed = TRUE; + break; + + case SCAN_F5: + gHotKey = FRONT_PAGE_KEY_DEVICE_MANAGER; + mHotKeyPressed = TRUE; + break; + + case SCAN_F7: + gHotKey = FRONT_PAGE_KEY_BOOT_MANAGER; + mHotKeyPressed = TRUE; + break; + + case SCAN_F9: + gHotKey = FRONT_PAGE_KEY_BOOT_MAINTAIN; + mHotKeyPressed = TRUE; + break; + } + + if (mHotKeyPressed) { + gBS->SetTimer ( + mHotKeyTimerEvent, + TimerCancel, + 0 + ); + gBS->CloseEvent (mHotKeyTimerEvent); + mHotKeyTimerEvent = NULL; + } + + return; +} + + +/** + Callback function for SimpleTextInEx protocol install events + + @param Event the event that is signaled. + @param Context not used here. + +**/ +VOID +EFIAPI +HitHotkeyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + Status = gBS->CloseEvent(mHitHotkeyEvent); + if (EFI_ERROR (Status)) { + return; + } + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + HotKeyTimerHandler, + NULL, + &mHotKeyTimerEvent + ); + if (EFI_ERROR (Status)) { + return; + } + Status = gBS->SetTimer ( + mHotKeyTimerEvent, + TimerPeriodic, + KEYBOARD_TIMER_INTERVAL + ); + if (EFI_ERROR (Status)) { + return; + } + + return; +} + + +VOID +EFIAPI +PlatformBdsInitHotKeyEvent ( + VOID + ) +{ + EFI_STATUS Status; + + // + // Register Protocol notify for Hotkey service + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + HitHotkeyEvent, + NULL, + &mHitHotkeyEvent + ); + ASSERT_EFI_ERROR (Status); + + // + // Register for protocol notifications on this event + // + Status = gBS->RegisterProtocolNotify ( + &gEfiSimpleTextInputExProtocolGuid, + mHitHotkeyEvent, + &mHitHotkeyRegistration + ); + ASSERT_EFI_ERROR (Status); +} diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.h b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.h new file mode 100644 index 0000000000..63972b51b8 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.h @@ -0,0 +1,484 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + BdsPlatform.h + +Abstract: + + Head file for BDS Platform specific code + +--*/ + +#ifndef _BDS_PLATFORM_H +#define _BDS_PLATFORM_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges []; +extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole []; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformAllPossiblePciVgaConsole []; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence []; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption []; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformBootOption []; +extern EFI_DEVICE_PATH_PROTOCOL *gUserAuthenticationDevice[]; +extern BDS_CONSOLE_CONNECT_ENTRY gPlatformSimpleConsole []; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformSimpleBootOption []; + +// +// the short form device path for Usb keyboard +// +#define CLASS_HID 3 +#define SUBCLASS_BOOT 1 +#define PROTOCOL_KEYBOARD 1 + +#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 gUart(BaudRate, DataBits, Parity, StopBits) \ + { \ + { \ + MESSAGING_DEVICE_PATH, \ + MSG_UART_DP, \ + { \ + (UINT8) (sizeof (UART_DEVICE_PATH)), \ + (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \ + } \ + }, \ + 0, \ + (BaudRate), \ + (DataBits), \ + (Parity), \ + (StopBits) \ + } + +#define gPcAnsiTerminal \ + { \ + { \ + MESSAGING_DEVICE_PATH, \ + MSG_VENDOR_DP, \ + { \ + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \ + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \ + } \ + }, \ + DEVICE_PATH_MESSAGING_PC_ANSI \ + } + +#define gUsbKeyboardMouse \ + { \ + { \ + MESSAGING_DEVICE_PATH, \ + MSG_USB_CLASS_DP, \ + (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)), \ + (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8) \ + }, \ + 0xffff, \ + 0xffff, \ + CLASS_HID, \ + SUBCLASS_BOOT, \ + PROTOCOL_KEYBOARD \ + } + +#define gEndEntire \ + { \ + END_DEVICE_PATH_TYPE, \ + END_ENTIRE_DEVICE_PATH_SUBTYPE, \ + { \ + END_DEVICE_PATH_LENGTH, \ + 0 \ + } \ + } + +#define gPciRootBridge \ + PNPID_DEVICE_PATH_NODE(0x0A03) + +#define gPnpPs2Keyboard \ + PNPID_DEVICE_PATH_NODE(0x0303) + +#define gPnp16550ComPort \ + PNPID_DEVICE_PATH_NODE(0x0501) + +#define gPciePort0Bridge \ + PCI_DEVICE_PATH_NODE(0, 0x1C) + +#define gPciePort1Bridge \ + PCI_DEVICE_PATH_NODE(1, 0x1C) + +#define gPciePort2Bridge \ + PCI_DEVICE_PATH_NODE(2, 0x1C) + +#define gPciePort3Bridge \ + PCI_DEVICE_PATH_NODE(3, 0x1C) + +#define gPciIsaBridge \ + PCI_DEVICE_PATH_NODE(0, 0x1f) + +// +// Platform Root Bridge +// +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_ROOT_BRIDGE_DEVICE_PATH; + +// +// Below is the platform console device path +// +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + PCI_DEVICE_PATH IsaBridge; + ACPI_HID_DEVICE_PATH Keyboard; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_ISA_KEYBOARD_DEVICE_PATH; + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_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 OnboardVga; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_ONBOARD_VGA_DEVICE_PATH; + +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + PCI_DEVICE_PATH AgpBridge; + PCI_DEVICE_PATH AgpDevice; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_OFFBOARD_VGA_DEVICE_PATH; + +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + PCI_DEVICE_PATH IsaBridge; + ACPI_HID_DEVICE_PATH IsaSerial; + UART_DEVICE_PATH Uart; + VENDOR_DEVICE_PATH TerminalType; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_ISA_SERIAL_DEVICE_PATH; + +// +// Below is the boot option device path +// +typedef struct { + BBS_BBS_DEVICE_PATH LegacyHD; + EFI_DEVICE_PATH_PROTOCOL End; +} LEGACY_HD_DEVICE_PATH; + +// +// Below is the platform IDE device path +// +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + PCI_DEVICE_PATH IsaBridge; + ATAPI_DEVICE_PATH Ide; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_IDE_DEVICE_PATH; + +// +// Floppy device path definition +// +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + PCI_DEVICE_PATH IsaBridge; + ACPI_HID_DEVICE_PATH Floppy; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_FLOPPY_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; + +// +// Below is the platform PCI device path +// +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + PCI_DEVICE_PATH PciDevice; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_PCI_DEVICE_PATH; + +typedef enum { + PMIC_Equal = 0, // = 0 + PMIC_Greater_Than, // > 1 + PMIC_Smaller_Than, // < 2 + PMIC_Greater_Equal, // >= 3 + PMIC_Smaller_Equal, // <= 4 + PMIC_Any // don't care 5 +} PMIC_Condition_list; + +typedef enum { + PMIC_White_List = 0, //White list + PMIC_Black_List = 1 //Black list +} PMIC_Compliance_mode; + +typedef struct { + UINT8 Cond_Choice; // PMIC_Condition_list + UINT8 Cond_Number; // the number +}PMIC_Condition_Item; + +typedef struct { + PMIC_Condition_Item PMIC_BoardID; + PMIC_Condition_Item PMIC_FabID; + PMIC_Condition_Item Soc_Stepping;//define PMIC type, 1:Dialog , 2:Rohm + PMIC_Condition_Item PMIC_VendID; + PMIC_Condition_Item PMIC_RevID; + PMIC_Compliance_mode mode; //if 1, blacklist; if 0, white list. +} PMIC_Compliance_Item; + +// +// Platform BDS Functions +// +VOID +PlatformBdsGetDriverOption ( + IN LIST_ENTRY *BdsDriverLists + ); + +VOID +PlatformBdsPredictBootOption ( + IN LIST_ENTRY *BdsBootOptionList + ); + +EFI_STATUS +PlatformBdsShowProgress ( + EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground, + EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground, + CHAR16 *Title, + EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor, + UINTN Progress, + UINTN PreviousValue + ); + +VOID +PlatformBdsConnectSequence ( + VOID + ); + +EFI_STATUS +PlatformBdsConnectConsole ( + IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole + ); + +EFI_STATUS +PlatformBdsNoConsoleAction ( + VOID + ); + +VOID +PlatformBdsEnterFrontPage ( + IN UINT16 TimeoutDefault, + IN BOOLEAN ConnectAllHappened + ); + +VOID +EFIAPI +PlatformBdsUserIdentify ( + OUT EFI_USER_PROFILE_HANDLE *User, + OUT BOOLEAN *DeferredImage + ); + +VOID +EFIAPI +PlatformBdsConnectAuthDevice ( + VOID + ); + +VOID +PlatformBdsEnterFrontPageWithHotKey ( + IN UINT16 TimeoutDefault, + IN BOOLEAN ConnectAllHappened + ); + + EFI_STATUS + ShowProgress ( + IN UINT16 TimeoutDefault + ); + + EFI_STATUS + InitializeFrontPage ( + IN BOOLEAN InitializeHiiData + ); + + VOID + UpdateFrontPageStrings ( + VOID + ); + + EFI_STATUS + CallFrontPage ( + VOID + ); + + + VOID + CallBootManager ( + VOID + ); + +VOID +CallDeviceManager ( + VOID + ); + +VOID +BdsStartBootMaint ( + VOID + ); + +CHAR16 * +GetStringById ( + IN EFI_STRING_ID Id + ); + +EFI_STATUS +WaitForSingleEvent ( + IN EFI_EVENT Event, + IN UINT64 Timeout OPTIONAL + ); + + +#define ONE_SECOND 10000000 +#define FRONT_PAGE_KEY_CONTINUE 0x1000 +#define FRONT_PAGE_KEY_LANGUAGE 0x1234 +#define FRONT_PAGE_KEY_BOOT_MANAGER 0x1064 +#define FRONT_PAGE_KEY_DEVICE_MANAGER 0x8567 +#define FRONT_PAGE_KEY_BOOT_MAINTAIN 0x9876 + +#define PORT_A_DVO 0 // ; DVO A +#define PORT_B_DVO 1 // ; DVO B +#define PORT_C_DVO 2 // ; DVO C +#define PORT_D_DVO 3 // ; DVO D +#define PORT_LVDS 4 // ; Integrated LVDS port +#define PORT_ANALOG_TV 5 // ; Integrated TV port +#define PORT_CRT 6 // ; integrated Analog port +#define PORT_B_DP 7 // ; DisplayPort B +#define PORT_C_DP 8 // ; DisplayPort C +#define PORT_D_DP 9 // ; DisplayPort D +#define PORT_A_DP 10 // ; DisplayPort A (for eDP on ILK) +#define PORT_B_HDMI 11 // ; HDMI B +#define PORT_C_HDMI 12 // ; HDMI C +#define PORT_D_HDMI 13 // ; HDMI D +#define PORT_B_DVI 14 // ; DVI B +#define PORT_C_DVI 15 // ; DVI C +#define PORT_D_DVI 16 // ; DVI D +#define PORT_MIPI_A 21 // ; MIPI +#define PORT_MIPI_B 22 +#define PORT_MIPI_C 23 + + +extern BOOLEAN gConnectAllHappened; +extern UINTN gCallbackKey; + +VOID +BdsBootDeviceSelect ( + VOID +); +VOID FastBoot(VOID); + +extern BOOLEAN mModeInitialized; + +// +// Boot video resolution and text mode. +// +extern UINT32 mBootHorizontalResolution ; +extern UINT32 mBootVerticalResolution ; +extern UINT32 mBootTextModeColumn ; +extern UINT32 mBootTextModeRow ; + +// +// BIOS setup video resolution and text mode. +// +extern UINT32 mSetupTextModeColumn ; +extern UINT32 mSetupTextModeRow ; +extern UINT32 mSetupHorizontalResolution ; +extern UINT32 mSetupVerticalResolution ; +extern EFI_STATUS BdsSetConsoleMode (BOOLEAN); +#endif // _BDS_PLATFORM_H diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf new file mode 100644 index 0000000000..31ff8b895c --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformBdsLib.inf @@ -0,0 +1,118 @@ +#/** @file +# Component name for module PlatformBootManagerLib +# +# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformBdsLib + FILE_GUID = A6BC385D-59E5-4b77-87D7-200ABAA83C15 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x0002000A + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + BdsPlatform.c + BdsPlatform.h + PlatformData.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + ShellPkg/ShellPkg.dec + CryptoPkg/CryptoPkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + DxeServicesTableLib + BaseLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseMemoryLib + DebugLib + PcdLib + GenericBdsLib + DevicePathLib + UefiLib + HobLib + PciLib + PrintLib + BaseCryptLib +# TcgPhysicalPresenceLib +# TrEEPhysicalPresenceLib + FileHandleLib + S3BootScriptLib + SerialPortLib + +[Protocols] + gEfiFirmwareVolume2ProtocolGuid + gEfiSimpleNetworkProtocolGuid + gEfiLoadFileProtocolGuid + gEfiPciIoProtocolGuid + gEfiSmmAccess2ProtocolGuid + gEfiDxeSmmReadyToLockProtocolGuid + gEfiUserManagerProtocolGuid + gEfiDeferredImageLoadProtocolGuid + gEfiAcpiS3SaveProtocolGuid + gEfiSpiProtocolGuid ## PROTOCOL CONSUMES + gExitPmAuthProtocolGuid + gEfiTdtOperationProtocolGuid + gEfiGlobalNvsAreaProtocolGuid + gEfiMmioDeviceProtocolGuid + gEfiI2cMasterProtocolGuid + gEfiI2cHostProtocolGuid + +[Guids] + gEfiMemoryTypeInformationGuid + gEfiCapsuleVendorGuid + gEfiGlobalVariableGuid + gEfiNormalSetupGuid + gEfiPartTypeSystemPartGuid + +[Pcd] + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Base + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainBase + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoveryBase + gPlatformModuleTokenSpaceGuid.PcdFlashFvShellBase + gPlatformModuleTokenSpaceGuid.PcdFlashFvShellSize + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile + gPlatformModuleTokenSpaceGuid.PcdIFWISigBaseAddress + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupConOutColumn + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupConOutRow + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformData.c b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformData.c new file mode 100644 index 0000000000..64e68d3941 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/PlatformData.c @@ -0,0 +1,265 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +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 ISA keyboard device path +// +PLATFORM_ISA_KEYBOARD_DEVICE_PATH gIsaKeyboardDevicePath = { + gPciRootBridge, + gPciIsaBridge, + gPnpPs2Keyboard, + gEndEntire +}; + +// +// Platform specific on chip PCI VGA device path +// +PLATFORM_ONBOARD_VGA_DEVICE_PATH gOnChipPciVgaDevicePath = { + gPciRootBridge, + PCI_DEVICE_PATH_NODE(0, 0x2), + gEndEntire +}; + +// +// Platform specific plug in PCI VGA device path +// +PLATFORM_OFFBOARD_VGA_DEVICE_PATH gPlugInPciVgaDevicePath = { + gPciRootBridge, + PCI_DEVICE_PATH_NODE(0, 0x1), + PCI_DEVICE_PATH_NODE(0, 0x0), + gEndEntire +}; + +// +// Platform specific ISA serial device path +// +PLATFORM_ISA_SERIAL_DEVICE_PATH gIsaSerialDevicePath = { + gPciRootBridge, + gPciIsaBridge, + gPnp16550ComPort, + gUart(115200, 8, 1, 1), + gPcAnsiTerminal, + gEndEntire +}; + + +// +// Platform specific Button Array device path +// +HII_VENDOR_DEVICE_PATH gHiiVendorDevicePath0 = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + + // + // {C8752FDE-B5C8-4528-897D-6920FE771E38} + // + { 0xC8752FDE, 0xB5C8, 0x4528, { 0x89, 0x7D, 0x69, 0x20, 0xFE, 0x77, 0x1E, 0x38 } } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = { + gUsbKeyboardMouse, + gEndEntire +}; + +// +// Predefined platform default console device path +// +BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole [] = { + {(EFI_DEVICE_PATH_PROTOCOL*)&gIsaSerialDevicePath, CONSOLE_ALL}, + {(EFI_DEVICE_PATH_PROTOCOL*)&gHiiVendorDevicePath0, CONSOLE_IN}, + {(EFI_DEVICE_PATH_PROTOCOL*)&gIsaKeyboardDevicePath, CONSOLE_IN}, + {(EFI_DEVICE_PATH_PROTOCOL*)&gUsbClassKeyboardDevicePath, CONSOLE_IN}, + {NULL, 0} +}; + +// +// All the possible platform PCI VGA device path +// +EFI_DEVICE_PATH_PROTOCOL* gPlatformAllPossiblePciVgaConsole [] = { + (EFI_DEVICE_PATH_PROTOCOL*)&gOnChipPciVgaDevicePath, + (EFI_DEVICE_PATH_PROTOCOL*)&gPlugInPciVgaDevicePath, + NULL +}; + +// +// Legacy hard disk boot option +// +LEGACY_HD_DEVICE_PATH gLegacyHd = { + { + BBS_DEVICE_PATH, + BBS_BBS_DP, + (UINT8)(sizeof(BBS_BBS_DEVICE_PATH)), + (UINT8)((sizeof(BBS_BBS_DEVICE_PATH)) >> 8), + BBS_TYPE_HARDDRIVE, + 0, + 0 + }, + gEndEntire +}; + +// +// Legacy cdrom boot option +// +LEGACY_HD_DEVICE_PATH gLegacyCdrom = { + { + BBS_DEVICE_PATH, + BBS_BBS_DP, + (UINT8)(sizeof(BBS_BBS_DEVICE_PATH)), + (UINT8)((sizeof(BBS_BBS_DEVICE_PATH)) >> 8), + BBS_TYPE_CDROM, + 0, + 0 + }, + gEndEntire +}; + +// +// Predefined platform specific perdict boot option +// +EFI_DEVICE_PATH_PROTOCOL* gPlatformBootOption [] = { + (EFI_DEVICE_PATH_PROTOCOL*)&gLegacyHd, + (EFI_DEVICE_PATH_PROTOCOL*)&gLegacyCdrom, + NULL +}; + +// +// Predefined platform specific driver option +// +EFI_DEVICE_PATH_PROTOCOL* gPlatformDriverOption [] = { + NULL +}; + +// +// Predefined platform connect sequence +// +EFI_DEVICE_PATH_PROTOCOL* gPlatformConnectSequence [] = { + (EFI_DEVICE_PATH_PROTOCOL *)&gPlatformRootBridge0, // Force PCI enumer before Legacy OpROM shadow + NULL +}; + +// +// Platform specific USB controller device path +// +PLATFORM_USB_DEVICE_PATH gUsbDevicePath0 = { + gPciRootBridge, + PCI_DEVICE_PATH_NODE(0, 0x1D), + gEndEntire +}; + +PLATFORM_USB_DEVICE_PATH gUsbDevicePath1 = { + gPciRootBridge, + PCI_DEVICE_PATH_NODE(1, 0x1D), + gEndEntire +}; + +PLATFORM_USB_DEVICE_PATH gUsbDevicePath2 = { + gPciRootBridge, + PCI_DEVICE_PATH_NODE(2, 0x1D), + gEndEntire +}; + +PLATFORM_USB_DEVICE_PATH gUsbDevicePath3 = { + gPciRootBridge, + PCI_DEVICE_PATH_NODE(3, 0x1D), + 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, + (EFI_DEVICE_PATH_PROTOCOL*)&gUsbDevicePath2, + (EFI_DEVICE_PATH_PROTOCOL*)&gUsbDevicePath3, + NULL +}; + +// +// Predefined platform console device path +// +BDS_CONSOLE_CONNECT_ENTRY gPlatformSimpleConsole [] = { + {(EFI_DEVICE_PATH_PROTOCOL*)&gOnChipPciVgaDevicePath, CONSOLE_OUT}, + {(EFI_DEVICE_PATH_PROTOCOL*)&gIsaSerialDevicePath, CONSOLE_ALL}, + {(EFI_DEVICE_PATH_PROTOCOL*)&gHiiVendorDevicePath0, CONSOLE_IN}, + {(EFI_DEVICE_PATH_PROTOCOL*)&gUsbClassKeyboardDevicePath, CONSOLE_IN}, + {NULL, 0} +}; + +// +// eMMC device at BDF(0x0, 0x17, 0x0) +// +PLATFORM_PCI_DEVICE_PATH gEmmcBootDevPath0 = { + gPciRootBridge, + PCI_DEVICE_PATH_NODE (0x00, 0x10), + gEndEntire +}; + +// +// Predefined platform specific perdict boot option +// +EFI_DEVICE_PATH_PROTOCOL* gPlatformSimpleBootOption [] = { + (EFI_DEVICE_PATH_PROTOCOL*)&gEmmcBootDevPath0, + NULL +}; + diff --git a/Vlv2TbltDevicePkg/Library/PlatformCmosLib/PlatformCmosLib.c b/Vlv2TbltDevicePkg/Library/PlatformCmosLib/PlatformCmosLib.c new file mode 100644 index 0000000000..10d0573bf3 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PlatformCmosLib/PlatformCmosLib.c @@ -0,0 +1,111 @@ +/*++ + +Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + CmosTable.h + +Abstract: + +--*/ + +#include +#include +#include +#include "CmosMap.h" +#include +#include "PlatformBaseAddresses.h" + +#define DEFAULT_VALUE 0 +#define DEFAULT_ATTRIBUTES 0 +#define EXCLUDE_FROM_CHECKSUM CMOS_ATTRIBUTE_EXCLUDE_FROM_CHECKSUM + +#define CMOS_DEBUG_PRINT_LEVEL_DEFAULT_VALUE 0x46 // EFI_D_WARN|EFI_D_INFO|EFI_D_LOAD +#define CMOS_DEBUG_PRINT_LEVEL_3_DEFAULT_VALUE 0x80 // EFI_D_ERROR + +// +// Add the CMOS entry below +// +CMOS_ENTRY mCmosTable[] = { +{ CPU_HT_POLICY, CPU_HT_POLICY_ENABLED, EXCLUDE_FROM_CHECKSUM }, +{ TPM_POLICY, TPM_POLICY_ENABLED, DEFAULT_ATTRIBUTES }, +{ CMOS_LCDPANELTYPE_REG, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_LCDPANELSCALING_REG, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_IGDBOOTTYPE_REG, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_BACKLIGHT_REG, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_LFP_PANEL_COLOR_DEPTH_REG, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_EDP_ACTIVE_LFP_CONFIG_REG, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_PRIMARY_DISPLAY_REG, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_IGD_DISPLAY_PIPE_B_REG, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_SDVOPANELTYPE_REG, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_PLATFORM_RESET_OS, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_CPU_BSP_SELECT, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_CPU_RATIO_OFFSET, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_ICH_PORT80_OFFSET, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ CMOS_MAXRATIO_CONFIG_REG, DEFAULT_VALUE, DEFAULT_ATTRIBUTES }, +{ RTC_ADDRESS_CENTURY, RTC_ADDRESS_CENTURY_DEFAULT, CMOS_ATTRIBUTE_EXCLUDE_FROM_CHECKSUM }, +{ CMOS_POST_CODE_BREAK_REG, DEFAULT_VALUE, EXCLUDE_FROM_CHECKSUM }, +{ CMOS_POST_CODE_BREAK_1_REG, DEFAULT_VALUE, EXCLUDE_FROM_CHECKSUM }, +{ CMOS_POST_CODE_BREAK_2_REG, DEFAULT_VALUE, EXCLUDE_FROM_CHECKSUM }, +{ CMOS_POST_CODE_BREAK_3_REG, DEFAULT_VALUE, EXCLUDE_FROM_CHECKSUM }, +{ CMOS_DEBUG_PRINT_LEVEL_REG, CMOS_DEBUG_PRINT_LEVEL_DEFAULT_VALUE, EXCLUDE_FROM_CHECKSUM }, +{ CMOS_DEBUG_PRINT_LEVEL_1_REG, DEFAULT_VALUE, EXCLUDE_FROM_CHECKSUM }, +{ CMOS_DEBUG_PRINT_LEVEL_2_REG, DEFAULT_VALUE, EXCLUDE_FROM_CHECKSUM }, +{ CMOS_DEBUG_PRINT_LEVEL_3_REG, CMOS_DEBUG_PRINT_LEVEL_3_DEFAULT_VALUE, EXCLUDE_FROM_CHECKSUM }, +}; + +/** + Funtion to return platform CMOS entry. + + @param [out] CmosEntry Platform CMOS entry. + + @param [out] CmosEntryCount Number of platform CMOS entry. + + @return Status. +**/ +RETURN_STATUS +EFIAPI +GetPlatformCmosEntry ( + OUT CMOS_ENTRY **CmosEntry, + OUT UINTN *CmosEntryCount + ) +{ + *CmosEntry = mCmosTable; + *CmosEntryCount = sizeof(mCmosTable)/sizeof(mCmosTable[0]); + return RETURN_SUCCESS; +} + +/** + Function to check if Battery lost or CMOS cleared. + + @reval TRUE Battery is always present. + @reval FALSE CMOS is cleared. +**/ +BOOLEAN +EFIAPI +CheckCmosBatteryStatus ( + VOID + ) +{ + // + // Check if the CMOS battery is present + // Checks RTC_PWR_STS bit in the GEN_PMCON_1 register + // + + if ((MmioRead8 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1) & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) == 0) { + return TRUE; + } else { + return FALSE; + } +} diff --git a/Vlv2TbltDevicePkg/Library/PlatformCmosLib/PlatformCmosLib.inf b/Vlv2TbltDevicePkg/Library/PlatformCmosLib/PlatformCmosLib.inf new file mode 100644 index 0000000000..af91a298e5 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PlatformCmosLib/PlatformCmosLib.inf @@ -0,0 +1,35 @@ +#/** @file +# +# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformCmosLib + FILE_GUID = ECA883EF-0CBE-40b6-84BC-FA4A709782F7 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformCmosLib + +[Sources] + PlatformCmosLib.c + +[LibraryClasses] + IoLib + +[Packages] + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec diff --git a/Vlv2TbltDevicePkg/Library/PlatformFspLib/PlatformFspLib.c b/Vlv2TbltDevicePkg/Library/PlatformFspLib/PlatformFspLib.c new file mode 100644 index 0000000000..1306399545 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PlatformFspLib/PlatformFspLib.c @@ -0,0 +1,49 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ +#include "PiPei.h" +#include +#include +#include +#include +#include + +EFI_STATUS +PlatformHobCreateFromFsp ( + IN CONST EFI_PEI_SERVICES **PeiServices, + VOID *HobList + ) +{ + VOID *HobData; + VOID *NewHobData; + UINTN DataSize; + + // + // Other hob, todo: put this into FspWrapPlatformLib + // + if ((HobList = GetNextGuidHob (&gEfiMemoryConfigDataGuid, HobList)) != NULL) { + HobData = GET_GUID_HOB_DATA (HobList); + DataSize = GET_GUID_HOB_DATA_SIZE(HobList); + DEBUG((EFI_D_ERROR, "gEfiMemoryConfigDataGuid Hob found: 0x%x.\n", DataSize)); + + NewHobData = BuildGuidHob (&gEfiMemoryConfigDataGuid, DataSize); + (*PeiServices)->CopyMem ( + NewHobData, + HobData, + DataSize + ); + } + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/Library/PlatformFspLib/PlatformFspLib.inf b/Vlv2TbltDevicePkg/Library/PlatformFspLib/PlatformFspLib.inf new file mode 100644 index 0000000000..e64ceacb0d --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/PlatformFspLib/PlatformFspLib.inf @@ -0,0 +1,54 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +# FSP Platform HOB Library +# +# +# +## + + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformFspLib + FILE_GUID = 1305A712-33A6-4fa7-BA59-AEAC3362931A + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformFspLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + PlatformFspLib.c + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + IntelFspWrapperPkg/IntelFspWrapperPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + HobLib + +[Guids] + gEfiMemoryConfigDataGuid + diff --git a/Vlv2TbltDevicePkg/Library/ResetSystemLib/ResetSystemLib.c b/Vlv2TbltDevicePkg/Library/ResetSystemLib/ResetSystemLib.c new file mode 100644 index 0000000000..1a6da83c40 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/ResetSystemLib/ResetSystemLib.c @@ -0,0 +1,178 @@ +/** @file + +Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + IdeBus.h + +Abstract: + + System reset Library Services. This library class provides a set of + methods to reset whole system with manipulate ICH. + +**/ + + +#include + + +#include +#include +#include +#include +#include + +#include "PchRegs.h" +#include "Rsci.h" +#include "Platform.h" + +#define RESET_GENERATOR_PORT R_PCH_RST_CNT + +VOID +EFIAPI +PlatformResetHook ( + UINT8 ResetType + ) +{ + // + // Platform need to save OS reset request/types for next Android boot + // + IoWrite8 (0x72, CMOS_RESET_TYPE_BY_OS); + IoWrite8 (0x73, ResetType); +} + +/** + 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 + ) +{ + PlatformResetHook(COLD_RESET); + IoWrite8 (RESET_GENERATOR_PORT, 0x2); + IoWrite8 (RESET_GENERATOR_PORT, 0x6); +} + +/** + 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 + ) +{ + PlatformResetHook(WARM_RESET); + IoWrite8 (RESET_GENERATOR_PORT, 0x0); + IoWrite8 (RESET_GENERATOR_PORT, 0x4); +} + +/** + 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 + ) +{ + UINT16 PchPmioBase; + UINT16 Data16; + UINT32 Data32; + + PchPmioBase = (UINT16) (PciRead16 (PCI_LIB_ADDRESS(0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_ACPI_BASE)) & ~BIT0); + + // + // Then, GPE0_EN should be disabled to avoid any GPI waking up the system from S5 + // + Data16 = 0; + IoWrite16 ( + (UINTN)(PchPmioBase + R_PCH_ACPI_GPE0a_EN), + (UINT16)Data16 + ); + + // + // Clear Sleep SMI Status + // + IoWrite16 (PchPmioBase + R_PCH_SMI_STS, + (UINT16)(IoRead16 (PchPmioBase + R_PCH_SMI_STS) | B_PCH_SMI_STS_ON_SLP_EN)); + // + // Clear Sleep Type Enable + // + IoWrite16 (PchPmioBase + R_PCH_SMI_EN, + (UINT16)(IoRead16 (PchPmioBase + R_PCH_SMI_EN) & (~B_PCH_SMI_EN_ON_SLP_EN))); + // + // Clear Power Button Status + // + IoWrite16(PchPmioBase + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_PWRBTN); + + // + // Secondly, Power Button Status bit must be cleared + // + // Write a "1" to bit[8] of power button status register at + // (ABASE + PM1_STS) to clear this bit + // Clear it through SMI Status register + // + Data16 = B_PCH_SMI_STS_PM1_STS_REG; + IoWrite16 ((UINTN) (PchPmioBase + R_PCH_SMI_STS), Data16); + + // + // Finally, transform system into S5 sleep state + // + Data32 = IoRead32 ((UINTN) (PchPmioBase + R_PCH_ACPI_PM1_CNT)); + + Data32 = (UINT32) ((Data32 &~(B_PCH_ACPI_PM1_CNT_SLP_TYP + B_PCH_ACPI_PM1_CNT_SLP_EN)) | V_PCH_ACPI_PM1_CNT_S5); + + IoWrite32 ((UINTN) (PchPmioBase + R_PCH_ACPI_PM1_CNT), Data32); + + Data32 = Data32 | B_PCH_ACPI_PM1_CNT_SLP_EN; + + IoWrite32 ((UINTN) (PchPmioBase + R_PCH_ACPI_PM1_CNT), Data32); + + return; +} + +/** + 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 + ) +{ + ASSERT (FALSE); +} + diff --git a/Vlv2TbltDevicePkg/Library/ResetSystemLib/ResetSystemLib.inf b/Vlv2TbltDevicePkg/Library/ResetSystemLib/ResetSystemLib.inf new file mode 100644 index 0000000000..94b2c97a67 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/ResetSystemLib/ResetSystemLib.inf @@ -0,0 +1,52 @@ +#/** @file +# Component description file for Intel Ich7 Reset System Library. +# +# Reset System Library that layers on top of the I/O Library to directly +# access a standard SMBUS host controller. +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ResetSystemLib + FILE_GUID = D4FF05AA-3C7D-4b8a-A1EE-AA5EFA0B1732 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ResetSystemLib + 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 X64 IPF +# + +[Sources.common] + ResetSystemLib.c + + +[Packages] + Vlv2TbltDevicePkg/PlatformPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + +[LibraryClasses] + IoLib + BaseLib + DebugLib + PciLib diff --git a/Vlv2TbltDevicePkg/Library/SerialPortLib/PlatformSerialPortLib.h b/Vlv2TbltDevicePkg/Library/SerialPortLib/PlatformSerialPortLib.h new file mode 100644 index 0000000000..e59ae9279f --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/SerialPortLib/PlatformSerialPortLib.h @@ -0,0 +1,69 @@ +/** @file + Header file of Serial port hardware definition. + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + This software and associated documentation + (if any) is furnished under a license and may only be used or + copied in accordance with the terms of the license. Except as + permitted by such license, no part of this software or + documentation may be reproduced, stored in a retrieval system, or + transmitted in any form or by any means without the express written + consent of Intel Corporation. + + Module Name: PlatformSerialPortLib.h + +**/ + +#ifndef __PLATFORM_SERIAL_PORT_LIB_H_ +#define __PLATFORM_SERIAL_PORT_LIB_H_ + +#include +#include +#include +#include +#include + +// +// UART Register Offsets +// +#define BAUD_LOW_OFFSET 0x00 +#define BAUD_HIGH_OFFSET 0x01 +#define IER_OFFSET 0x01 +#define LCR_SHADOW_OFFSET 0x01 +#define FCR_SHADOW_OFFSET 0x02 +#define IR_CONTROL_OFFSET 0x02 +#define FCR_OFFSET 0x02 +#define EIR_OFFSET 0x02 +#define BSR_OFFSET 0x03 +#define LCR_OFFSET 0x03 +#define MCR_OFFSET 0x04 +#define LSR_OFFSET 0x05 +#define MSR_OFFSET 0x06 + +// +// UART Register Bit Defines +// +#define LSR_TXRDY 0x20 +#define LSR_RXDA 0x01 +#define DLAB 0x01 + +#define UART_DATA 8 +#define UART_STOP 1 +#define UART_PARITY 0 +#define UART_BREAK_SET 0 + +VOID +InitializeSio ( + VOID + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Library/SerialPortLib/SerialPortLib.c b/Vlv2TbltDevicePkg/Library/SerialPortLib/SerialPortLib.c new file mode 100644 index 0000000000..21d5e8aec5 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/SerialPortLib/SerialPortLib.c @@ -0,0 +1,262 @@ +/** @file + Serial I/O Port library functions with no library constructor/destructor + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + This software and associated documentation + (if any) is furnished under a license and may only be used or + copied in accordance with the terms of the license. Except as + permitted by such license, no part of this software or + documentation may be reproduced, stored in a retrieval system, or + transmitted in any form or by any means without the express written + consent of Intel Corporation. + + Module Name: SerialPortLib.c + +**/ + +#include "PlatformSerialPortLib.h" + +UINT16 gComBase = 0x3f8; +UINTN gBps = 115200; +UINT8 gData = 8; +UINT8 gStop = 1; +UINT8 gParity = 0; +UINT8 gBreakSet = 0; + +/** + Initialize Serial Port + + The Baud Rate Divisor registers are programmed and the LCR + is used to configure the communications format. Hard coded + UART config comes from globals in DebugSerialPlatform lib. + + @param None + + @retval None + +**/ +RETURN_STATUS +EFIAPI +UARTInitialize ( + VOID + ) +{ + UINTN Divisor; + UINT8 OutputData; + UINT8 Data; + + // + // Map 5..8 to 0..3 + // + Data = (UINT8) (gData - (UINT8) 5); + + // + // Calculate divisor for baud generator + // + Divisor = 115200 / gBps; + + // + // Set communications format + // + OutputData = (UINT8) ((DLAB << 7) | ((gBreakSet << 6) | ((gParity << 3) | ((gStop << 2) | Data)))); + IoWrite8 (gComBase + LCR_OFFSET, OutputData); + + // + // Configure baud rate + // + IoWrite8 (gComBase + BAUD_HIGH_OFFSET, (UINT8) (Divisor >> 8)); + IoWrite8 (gComBase + BAUD_LOW_OFFSET, (UINT8) (Divisor & 0xff)); + + // + // Switch back to bank 0 + // + OutputData = (UINT8) ((~DLAB << 7) | ((gBreakSet << 6) | ((gParity << 3) | ((gStop << 2) | Data)))); + IoWrite8 (gComBase + LCR_OFFSET, OutputData); + + return RETURN_SUCCESS; +} + +/** + Common function to initialize UART Serial device and USB Serial device. + + @param None + + @retval None + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + + UARTInitialize (); + + + return RETURN_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 +UARTDbgOut ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINTN Result; + UINT8 Data; + + if (NULL == Buffer) { + return 0; + } + + Result = NumberOfBytes; + + while (NumberOfBytes--) { + // + // Wait for the serial port to be ready. + // + do { + Data = IoRead8 ((UINT16) PcdGet64 (PcdSerialRegisterBase) + LSR_OFFSET); + } while ((Data & LSR_TXRDY) == 0); + IoWrite8 ((UINT16) PcdGet64 (PcdSerialRegisterBase), *Buffer++); + } + + return Result; +} + +/** + Common function to write data to UART Serial device and USB Serial device. + + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + if (FeaturePcdGet (PcdStatusCodeUseIsaSerial)) { + UARTDbgOut (Buffer, NumberOfBytes); + } + + return RETURN_SUCCESS; +} + +/** + 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 +UARTDbgIn ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINTN Result; + UINT8 Data; + + if (NULL == Buffer) { + return 0; + } + + Result = NumberOfBytes; + + while (NumberOfBytes--) { + // + // Wait for the serial port to be ready. + // + do { + Data = IoRead8 ((UINT16) PcdGet64 (PcdSerialRegisterBase) + LSR_OFFSET); + } while ((Data & LSR_RXDA) == 0); + + *Buffer++ = IoRead8 ((UINT16) PcdGet64 (PcdSerialRegisterBase)); + } + + return Result; +} + +/** + Common function to Read data from UART serial device, USB serial device and save the datas in buffer. + + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + if (FeaturePcdGet (PcdStatusCodeUseIsaSerial)) { + UARTDbgIn (Buffer, NumberOfBytes); + } + + return RETURN_SUCCESS; +} + + +/** + Polls a serial device to see if there is any data waiting to be read. + + Polls aserial device to see if there is any data waiting to be read. + If there is data waiting to be read from the serial device, then TRUE is returned. + If there is no data waiting to be read from the serial device, then FALSE is returned. + + @retval TRUE Data is waiting to be read from the serial device. + @retval FALSE There is no data waiting to be read from the serial device. + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + UINT8 Data; + + // + // Read the serial port status. + // + Data = IoRead8 ((UINT16) PcdGet64 (PcdSerialRegisterBase) + LSR_OFFSET); + + return (BOOLEAN) ((Data & LSR_RXDA) != 0); +} diff --git a/Vlv2TbltDevicePkg/Library/SerialPortLib/SerialPortLib.inf b/Vlv2TbltDevicePkg/Library/SerialPortLib/SerialPortLib.inf new file mode 100644 index 0000000000..92cdf9965c --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/SerialPortLib/SerialPortLib.inf @@ -0,0 +1,57 @@ +#/** @file +# +# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SerialPortLib + FILE_GUID = 15B26F43-A389-4bae-BDE3-4BB0719B7D4F + 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 +# + +[Sources] + SerialPortLib.c + SioInit.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + +[LibraryClasses] + BaseLib + PcdLib + IoLib + PciLib + TimerLib + +[FixedPcd.common] + gEfiSerialPortTokenSpaceGuid.PcdSerialBoudRate + gEfiSerialPortTokenSpaceGuid.PcdSerialRegisterBase + +[FeaturePcd] + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseIsaSerial + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseUsbSerial + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseRam diff --git a/Vlv2TbltDevicePkg/Library/SerialPortLib/SioInit.c b/Vlv2TbltDevicePkg/Library/SerialPortLib/SioInit.c new file mode 100644 index 0000000000..78a380aff9 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/SerialPortLib/SioInit.c @@ -0,0 +1,132 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + SioInit.c + +Abstract: + + Functions for LpcSio initialization + +--*/ + +#include "PlatformSerialPortLib.h" +#include "SioInit.h" + +typedef struct { + UINT8 Register; + UINT8 Value; +} EFI_SIO_TABLE; + +EFI_SIO_TABLE mSioTableWpcn381u[] = { + {0x29, 0x0A0}, + {WPCN381U_LD_SEL_REGISTER, WPCN381U_LDN_UART0}, // Select UART0 device + {WPCN381U_BASE1_HI_REGISTER, (UINT8)(WPCN381U_SERIAL_PORT0_BASE_ADDRESS >> 8)}, // Set Base Address MSB + {WPCN381U_BASE1_LO_REGISTER, (UINT8)(WPCN381U_SERIAL_PORT0_BASE_ADDRESS & 0x00FF)}, // Set Base Address LSB + {WPCN381U_IRQ1_REGISTER, 0x014}, // Set to IRQ4 + {WPCN381U_ACTIVATE_REGISTER, WPCN381U_ACTIVATE_VALUE}, // Enable it with Activation bit + {WPCN381U_LD_SEL_REGISTER, WPCN381U_LDN_UART1}, // Select UART1 device + {WPCN381U_BASE1_HI_REGISTER, (UINT8)(WPCN381U_SERIAL_PORT1_BASE_ADDRESS >> 8)}, // Set Base Address MSB + {WPCN381U_BASE1_LO_REGISTER, (UINT8)(WPCN381U_SERIAL_PORT1_BASE_ADDRESS & 0x00FF)}, // Set Base Address LSB + {WPCN381U_IRQ1_REGISTER, 0x013}, // Set to IRQ3 + {WPCN381U_ACTIVATE_REGISTER, WPCN381U_ACTIVATE_VALUE}, // Enable it with Activation bit + {WPCN381U_LD_SEL_REGISTER, WPCN381U_LDN_GPIO}, // Select GPIO device + {WPCN381U_BASE1_HI_REGISTER, (UINT8)(WPCN381U_GPIO_BASE_ADDRESS >> 8)}, // Set Base Address MSB + {WPCN381U_BASE1_LO_REGISTER, (UINT8)(WPCN381U_GPIO_BASE_ADDRESS & 0x00FF)}, // Set Base Address LSB + {WPCN381U_ACTIVATE_REGISTER, WPCN381U_ACTIVATE_VALUE}, // Enable it with Activation bit + {0x21, 0x001}, // Global Device Enable + {0x26, 0x000} +}; + +EFI_SIO_TABLE mSioTableWdcp376[] = { + {0x29, 0x0A0}, + {WPCN381U_LD_SEL_REGISTER, WPCN381U_LDN_UART0}, // Select UART0 device + {WPCN381U_BASE1_HI_REGISTER, (UINT8)(WPCN381U_SERIAL_PORT0_BASE_ADDRESS >> 8)}, // Set Base Address MSB + {WPCN381U_BASE1_LO_REGISTER, (UINT8)(WPCN381U_SERIAL_PORT0_BASE_ADDRESS & 0x00FF)}, // Set Base Address LSB + {WPCN381U_IRQ1_REGISTER, 0x014}, // Set to IRQ4 + {WPCN381U_ACTIVATE_REGISTER, WPCN381U_ACTIVATE_VALUE}, // Enable it with Activation bit + {WPCN381U_LD_SEL_REGISTER, WPCN381U_LDN_UART1}, // Select UART1 device + {WPCN381U_BASE1_HI_REGISTER, (UINT8)(WPCN381U_SERIAL_PORT1_BASE_ADDRESS >> 8)}, // Set Base Address MSB + {WPCN381U_BASE1_LO_REGISTER, (UINT8)(WPCN381U_SERIAL_PORT1_BASE_ADDRESS & 0x00FF)}, // Set Base Address LSB + {WPCN381U_IRQ1_REGISTER, 0x013}, // Set to IRQ3 + {WPCN381U_ACTIVATE_REGISTER, WPCN381U_ACTIVATE_VALUE}, // Enable it with Activation bit + {WPCN381U_LD_SEL_REGISTER, WPCN381U_LDN_GPIO}, // Select GPIO device + {WPCN381U_BASE1_HI_REGISTER, (UINT8)(WPCN381U_GPIO_BASE_ADDRESS >> 8)}, // Set Base Address MSB + {WPCN381U_BASE1_LO_REGISTER, (UINT8)(WPCN381U_GPIO_BASE_ADDRESS & 0x00FF)}, // Set Base Address LSB + {WPCN381U_ACTIVATE_REGISTER, WPCN381U_ACTIVATE_VALUE}, // Enable it with Activation bit + {0x21, 0x001}, // Global Device Enable + {0x26, 0x000}, + {WPCN381U_LD_SEL_REGISTER, WPCN381U_LDN_PS2K}, // Select PS2 Keyboard + {WPCN381U_BASE1_HI_REGISTER, (UINT8)(WPCN381U_KB_BASE1_ADDRESS >> 8)}, // Set Base Address MSB + {WPCN381U_BASE1_LO_REGISTER, (UINT8)(WPCN381U_KB_BASE1_ADDRESS & 0x00FF)}, // Set Base Address LSB + {WPCN381U_BASE2_HI_REGISTER, (UINT8)(WPCN381U_KB_BASE2_ADDRESS >> 8)}, // Set Base Address MSB + {WPCN381U_BASE2_LO_REGISTER, (UINT8)(WPCN381U_KB_BASE2_ADDRESS & 0x00FF)}, // Set Base Address LSB + {WPCN381U_IRQ1_REGISTER, 0x011}, // Set to IRQ1 + {0xF0, (SIO_KBC_CLOCK << 6)}, // Select KBC Clock Source + {WPCN381U_ACTIVATE_REGISTER, WPCN381U_ACTIVATE_VALUE}, // Enable it with Activation bit + {WPCN381U_LD_SEL_REGISTER, WPCN381U_LDN_PS2M}, // Select PS2 Mouse + {WPCN381U_IRQ1_REGISTER, 0x01c}, // Set to IRQ12 + {WPCN381U_ACTIVATE_REGISTER, WPCN381U_ACTIVATE_VALUE} // Enable it with Activation bit +}; + +/** + Initialization for SIO. + + @param FfsHeader FV this PEIM was loaded from. + @param PeiServices General purpose services available to every PEIM. + + None + +**/ +VOID +InitializeSio ( + VOID + ) +{ + UINT16 Index; + UINT16 IndexPort; + UINT16 DataPort; + + // + // Super I/O initialization for Winbond WPCN381U + // + IndexPort = WPCN381U_CONFIG_INDEX; + DataPort = WPCN381U_CONFIG_DATA; + + // + // Check for Winbond WPCN381U + // + IoWrite8 (IndexPort, WPCN381U_DEV_ID_REGISTER); // Winbond WPCN381U Device ID register is 0x20 + + if (IoRead8 (DataPort) == WPCN381U_CHIP_ID) { // Winbond WPCN381U Device ID is 0xF4 + // + // Configure WPCN381U SIO + // + for (Index = 0; Index < sizeof (mSioTableWpcn381u) / sizeof (EFI_SIO_TABLE); Index++) { + IoWrite8 (IndexPort, mSioTableWpcn381u[Index].Register); + IoWrite8 (DataPort, mSioTableWpcn381u[Index].Value); + } + } + + if (IoRead8 (DataPort) == WDCP376_CHIP_ID) { // Winbond WDCP376 Device ID is 0xF1 + // + // Configure WDCP376 SIO + // + for (Index = 0; Index < sizeof (mSioTableWdcp376) / sizeof (EFI_SIO_TABLE); Index++) { + IoWrite8 (IndexPort, mSioTableWdcp376[Index].Register); + IoWrite8 (DataPort, mSioTableWdcp376[Index].Value); + } + } + return; +} diff --git a/Vlv2TbltDevicePkg/Library/SerialPortLib/SioInit.h b/Vlv2TbltDevicePkg/Library/SerialPortLib/SioInit.h new file mode 100644 index 0000000000..cded45c7e1 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/SerialPortLib/SioInit.h @@ -0,0 +1,78 @@ +/** @file + Header file of Serial port hardware definition. + + Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + This software and associated documentation + (if any) is furnished under a license and may only be used or + copied in accordance with the terms of the license. Except as + permitted by such license, no part of this software or + documentation may be reproduced, stored in a retrieval system, or + transmitted in any form or by any means without the express written + consent of Intel Corporation. + + Module Name: PlatformSerialPortLib.h + +**/ + +#ifndef _SIO_INIT_H_ +#define _SIO_INIT_H_ + +#define WPCN381U_CONFIG_INDEX 0x2E +#define WPCN381U_CONFIG_DATA 0x2F +#define WPCN381U_CONFIG_INDEX1 0x164E +#define WPCN381U_CONFIG_DATA1 0x164F +#define WPCN381U_CHIP_ID 0xF4 +#define WDCP376_CHIP_ID 0xF1 + +// +// SIO Logical Devices Numbers +// +#define WPCN381U_LDN_UART0 0x03 // LDN for Serial Port Controller +#define WPCN381U_LDN_UART1 0x02 // LDN for Parallel Port Controller +#define WPCN381U_LDN_PS2K 0x06 // LDN for PS2 Keyboard Controller +#define WPCN381U_LDN_PS2M 0x05 // LDN for PS2 Mouse Controller +#define WPCN381U_KB_BASE1_ADDRESS 0x60 // Base Address of KB controller +#define WPCN381U_KB_BASE2_ADDRESS 0x64 // Base Address of KB controller +#define SIO_KBC_CLOCK 0x01 // 0/1/2 - 8/12/16 MHz KBC Clock Source +#define WPCN381U_LDN_GPIO 0x07 // LDN for GPIO + +// +// SIO Registers Layout +// +#define WPCN381U_LD_SEL_REGISTER 0x07 // Logical Device Select Register Address +#define WPCN381U_DEV_ID_REGISTER 0x20 // Device Identification Register Address +#define WPCN381U_ACTIVATE_REGISTER 0x30 // Device Identification Register Address +#define WPCN381U_BASE1_HI_REGISTER 0x60 // Device BaseAddres Register #1 MSB Address +#define WPCN381U_BASE1_LO_REGISTER 0x61 // Device BaseAddres Register #1 LSB Address +#define WPCN381U_BASE2_HI_REGISTER 0x62 // Device BaseAddres Register #1 MSB Address +#define WPCN381U_BASE2_LO_REGISTER 0x63 // Device Ba1eAddres Register #1 LSB Address +#define WPCN381U_IRQ1_REGISTER 0x70 // Device IRQ Register #1 Address +#define WPCN381U_IRQ2_REGISTER 0x71 // Device IRQ Register #2 Address + +// +// SIO Activation Values +// +#define WPCN381U_ACTIVATE_VALUE 0x01 // Value to activate Device +#define WPCN381U_DEACTIVATE_VALUE 0x00 // Value to deactivate Device + +// +// SIO GPIO +// +#define WPCN381U_GPIO_BASE_ADDRESS 0x0A20 // SIO GPIO Base Address + +// +// SIO Serial Port Settings +// +#define WPCN381U_SERIAL_PORT0_BASE_ADDRESS 0x03F8 // Base Address of Serial Port 0 (COMA / UART0) +#define WPCN381U_SERIAL_PORT1_BASE_ADDRESS 0x02F8 // Base Address of Serial Port 1 (COMB / UART1) + +#endif diff --git a/Vlv2TbltDevicePkg/Library/SmbusLib/CommonHeader.h b/Vlv2TbltDevicePkg/Library/SmbusLib/CommonHeader.h new file mode 100644 index 0000000000..430672fa7d --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/SmbusLib/CommonHeader.h @@ -0,0 +1,31 @@ +/**@file + Common header file shared by all source files. + + This file includes package header files, library classes. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + +#include +#include + +#include +#include +#include +#include +#include + +#endif diff --git a/Vlv2TbltDevicePkg/Library/SmbusLib/SmbusLib.c b/Vlv2TbltDevicePkg/Library/SmbusLib/SmbusLib.c new file mode 100644 index 0000000000..8ca472da9b --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/SmbusLib/SmbusLib.c @@ -0,0 +1,878 @@ +/** @file + Intel ICH9 SMBUS library implementation built upon I/O library. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#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; + + IoPortBaseAddress = (UINTN) MmioRead32 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SMBUS, PCI_FUNCTION_NUMBER_PCH_SMBUS, R_PCH_SMBUS_BASE)) & B_PCH_SMBUS_BASE_BAR; + + // + // 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 + ) +{ + UINT8 HostStatus; + + HostStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS); + if ((HostStatus & B_PCH_SMBUS_IUS) != 0) { + return RETURN_TIMEOUT; + } else if ((HostStatus & B_PCH_SMBUS_HBSY) != 0) { + // + // Clear host status register and exit. + // + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL); + return RETURN_TIMEOUT; + } + // + // Clear out any odd status information (Will Not Clear In Use). + // + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, HostStatus); + + 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; + UINT8 AuxiliaryStatus; + + // + // Set Host Control Register (Initiate Operation, Interrupt disabled). + // + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCTL, (UINT8)(HostControl + B_PCH_SMBUS_START)); + + do { + // + // Poll INTR bit of Host Status Register. + // + HostStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS); + } while ((HostStatus & (B_PCH_SMBUS_INTR | B_PCH_SMBUS_ERRORS | B_PCH_SMBUS_BYTE_DONE_STS)) == 0); + + if ((HostStatus & B_PCH_SMBUS_ERRORS) == 0) { + return RETURN_SUCCESS; + } + + // + // Clear error bits of Host Status Register. + // + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_ERRORS); + + // + // Read Auxiliary Status Register to judge CRC error. + // + AuxiliaryStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS); + if ((AuxiliaryStatus & B_PCH_SMBUS_CRCE) != 0) { + return RETURN_CRC_ERROR; + } + + 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; + UINT8 AuxiliaryControl; + + IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress (); + + // + // Try to acquire the ownership of ICH SMBUS. + // + ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress); + if (RETURN_ERROR (ReturnStatus)) { + goto Done; + } + + // + // Set the appropriate Host Control Register and auxiliary Control Register. + // + AuxiliaryControl = 0; + if (SMBUS_LIB_PEC (SmBusAddress)) { + AuxiliaryControl |= B_PCH_SMBUS_AAC; + HostControl |= B_PCH_SMBUS_PEC_EN; + } + + // + // Set Host Command Register. + // + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress)); + + // + // Write value to Host Data 0 and Host Data 1 Registers. + // + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD0, (UINT8) Value); + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD1, (UINT8) (Value >> 8)); + + // + // Set Auxiliary Control Register. + // + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXC, AuxiliaryControl); + + // + // Set SMBUS slave address for the device to send/receive from. + // + IoWrite8 (IoPortBaseAddress + R_PCH_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_PCH_SMBUS_HD1) << 8); + Value = (UINT16)(Value | IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD0)); + + // + // Clear Host Status Register and Auxiliary Status Register. + // + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL); + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE); + +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_PCH_SMBUS_SMB_CMD_QUICK, + SmBusAddress | B_PCH_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_PCH_SMBUS_SMB_CMD_QUICK, + SmBusAddress | B_PCH_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 + ) +{ + UINT8 ValueReturn = 0; + + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + ValueReturn = (UINT8) InternalSmBusNonBlock ( + V_PCH_SMBUS_SMB_CMD_BYTE, + SmBusAddress | B_PCH_SMBUS_RW_SEL_READ, + 0, + Status + ); + return ValueReturn; + + } + +/** + 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 + ) +{ + UINT8 ValueReturn = 0; + + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + ValueReturn = (UINT8) InternalSmBusNonBlock ( + V_PCH_SMBUS_SMB_CMD_BYTE, + SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, + Value, + Status + ); + return ValueReturn; + + } + +/** + 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 + ) +{ + UINT8 ValueReturn = 0; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + ValueReturn = (UINT8) InternalSmBusNonBlock ( + V_PCH_SMBUS_SMB_CMD_BYTE_DATA, + SmBusAddress | B_PCH_SMBUS_RW_SEL_READ, + 0, + Status + ); + return ValueReturn; +} + +/** + 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 + ) +{ + UINT8 ValueReturn = 0; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + ValueReturn = (UINT8) InternalSmBusNonBlock ( + V_PCH_SMBUS_SMB_CMD_BYTE_DATA, + SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, + Value, + Status + ); + return ValueReturn; + +} + +/** + 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 + ) +{ + UINT16 ValueReturn = 0; + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + ValueReturn = InternalSmBusNonBlock ( + V_PCH_SMBUS_SMB_CMD_WORD_DATA, + SmBusAddress | B_PCH_SMBUS_RW_SEL_READ, + 0, + Status + ); + return ValueReturn; + +} + +/** + 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 + ) +{ + UINT16 ValueReturn = 0; + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + ValueReturn = InternalSmBusNonBlock ( + V_PCH_SMBUS_SMB_CMD_WORD_DATA, + SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, + Value, + Status + ); + return ValueReturn; +} + +/** + 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 + ) +{ + UINT16 ValueReturn = 0; + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + ValueReturn = InternalSmBusNonBlock ( + V_PCH_SMBUS_SMB_CMD_PROCESS_CALL, + SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, + Value, + Status + ); + return ValueReturn; +} + +/** + 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; + UINT8 AuxiliaryControl; + + 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 the appropriate Host Control Register and auxiliary Control Register. + // + AuxiliaryControl = B_PCH_SMBUS_E32B; + if (SMBUS_LIB_PEC (SmBusAddress)) { + AuxiliaryControl |= B_PCH_SMBUS_AAC; + HostControl |= B_PCH_SMBUS_PEC_EN; + } + + // + // Set Host Command Register. + // + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress)); + + // + // Set Auxiliary Control Regiester. + // + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXC, AuxiliaryControl); + + // + // Clear byte pointer of 32-byte buffer. + // + IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HCTL); + + if (WriteBuffer != NULL) { + // + // Write the number of block to Host Block Data Byte Register. + // + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD0, (UINT8) BytesCount); + + // + // Write data block to Host Block Data Register. + // + for (Index = 0; Index < BytesCount; Index++) { + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HBD, WriteBuffer[Index]); + } + } + + // + // Set SMBUS slave address for the device to send/receive from. + // + IoWrite8 (IoPortBaseAddress + R_PCH_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_PCH_SMBUS_HD0); + + // + // Write data block from Host Block Data Register. + // + for (Index = 0; Index < BytesCount; Index++) { + ReadBuffer[Index] = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HBD); + } + } + +Done: + // + // Clear Host Status Register and Auxiliary Status Register. + // + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL); + IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE); + + 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 + ) +{ + UINTN BytesCount = 0; + + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + + BytesCount = InternalSmBusBlock ( + V_PCH_SMBUS_SMB_CMD_BLOCK, + SmBusAddress | B_PCH_SMBUS_RW_SEL_READ, + NULL, + Buffer, + Status + ); + return BytesCount; + +} + +/** + 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 + ) +{ + UINTN BytesCount = 0; + + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + + BytesCount = InternalSmBusBlock ( + + V_PCH_SMBUS_SMB_CMD_BLOCK, + SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, + Buffer, + NULL, + Status + ); + + return BytesCount; +} + +/** + Executes an SMBUS block process call command. + + Executes an SMBUS block process call 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 WriteBuffer. Bytes are then read from the SMBUS into ReadBuffer. + 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 ReadBuffer 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 zero or greater than 32, then ASSERT(). + If WriteBuffer is NULL, then ASSERT(). + If ReadBuffer 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 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 written. + +**/ +UINTN +EFIAPI +SmBusBlockProcessCall ( + IN UINTN SmBusAddress, + IN VOID *WriteBuffer, + OUT VOID *ReadBuffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINTN BytesCount = 0; + + ASSERT (WriteBuffer != NULL); + ASSERT (ReadBuffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32); + ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0); + + BytesCount = InternalSmBusBlock ( + V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS, + SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE, + WriteBuffer, + ReadBuffer, + Status + ); + return BytesCount; + + } diff --git a/Vlv2TbltDevicePkg/Library/SmbusLib/SmbusLib.inf b/Vlv2TbltDevicePkg/Library/SmbusLib/SmbusLib.inf new file mode 100644 index 0000000000..ac05aea941 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/SmbusLib/SmbusLib.inf @@ -0,0 +1,51 @@ +## @file +# Component description file for Intel Ich9 Smbus Library. +# +# SMBUS Library that layers on top of the I/O Library to directly +# access a standard SMBUS host controller. +# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmbusLib + FILE_GUID = 0558CAEA-FEF3-4b6d-915E-8742EFE6DEE1 + 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 + +[Packages] + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + MdePkg/MdePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + +[LibraryClasses] + PcdLib + DebugLib + PciLib + IoLib + +[Pcd.common] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + diff --git a/Vlv2TbltDevicePkg/Library/StallSmmLib/StallSmm.c b/Vlv2TbltDevicePkg/Library/StallSmmLib/StallSmm.c new file mode 100644 index 0000000000..80fa8173b7 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/StallSmmLib/StallSmm.c @@ -0,0 +1,94 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + SmmIo.c + +Abstract: + + SMM I/O access utility implementation file, for Ia32 + +--*/ + +// +// Include files +// +#include "Library/StallSmmLib.h" +#include "Pi/PiSmmCis.h" +#include "PiDxe.h" +#include +#include +#include "PchAccess.h" + +/** + Delay for at least the request number of microseconds. + Timer used is ACPI time counter, which has 1us granularity. + + @param Microseconds Number of microseconds to delay. + + @retval None + +**/ +VOID +SmmStall ( + IN UINTN Microseconds + ) +{ + UINTN Ticks; + UINTN Counts; + UINTN CurrentTick; + UINTN OriginalTick; + UINTN RemainingTick; + UINT16 AcpiBaseAddr; + + if (Microseconds == 0) { + return; + } + + AcpiBaseAddr = PchLpcPciCfg16 (R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR; + + OriginalTick = IoRead32 (AcpiBaseAddr + R_PCH_ACPI_PM1_TMR); + CurrentTick = OriginalTick; + + // + // The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks + // + Ticks = Microseconds * 358 / 100 + OriginalTick + 1; + + // + // The loops needed by timer overflow + // + Counts = Ticks / V_PCH_ACPI_PM1_TMR_MAX_VAL; + + // + // Remaining clocks within one loop + // + RemainingTick = Ticks % V_PCH_ACPI_PM1_TMR_MAX_VAL; + + // + // not intend to use TMROF_STS bit of register PM1_STS, because this adds extra + // one I/O operation, and maybe generate SMI + // + while ((Counts != 0) || (RemainingTick > CurrentTick)) { + CurrentTick = IoRead32 (AcpiBaseAddr + R_PCH_ACPI_PM1_TMR); + // + // Check if timer overflow + // + if (CurrentTick < OriginalTick) { + Counts--; + } + OriginalTick = CurrentTick; + } +} diff --git a/Vlv2TbltDevicePkg/Library/StallSmmLib/StallSmmLib.inf b/Vlv2TbltDevicePkg/Library/StallSmmLib/StallSmmLib.inf new file mode 100644 index 0000000000..a3134816a8 --- /dev/null +++ b/Vlv2TbltDevicePkg/Library/StallSmmLib/StallSmmLib.inf @@ -0,0 +1,56 @@ +#/*++ +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +# +# Module Name: +# +# SmmStallLib.inf +# +# Abstract: +# +# Component description file for SmmStall library +# +#--*/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = StallSmmLib + FILE_GUID = A6A16CCB-91B0-42f4-B4F3-D16D7A8662E6 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = StallSmmLib + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + StallSmm.c + + +[Packages] + MdePkg/MdePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + +[LibraryClasses] + PcdLib + PciLib + IoLib + BaseLib + +[Pcd.common] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress diff --git a/Vlv2TbltDevicePkg/Logo/Logo.bmp b/Vlv2TbltDevicePkg/Logo/Logo.bmp new file mode 100644 index 0000000000000000000000000000000000000000..26ac1a81dad1de6c6f94c27b91d448300a339059 GIT binary patch literal 94434 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 e0h + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + LegacyMetronome.c + +Abstract: + + This contains the installation function for the driver. + +--*/ + +#include "LegacyMetronome.h" + +// +// Handle for the Metronome Architectural Protocol instance produced by this driver +// +EFI_HANDLE mMetronomeHandle = NULL; + +// +// The Metronome Architectural Protocol instance produced by this driver +// +EFI_METRONOME_ARCH_PROTOCOL mMetronome = { + WaitForTick, + TICK_PERIOD +}; + +// +// The CPU I/O Protocol used to access system hardware +// +EFI_CPU_IO_PROTOCOL *mCpuIo = NULL; + +// +// Worker Functions +// + +/** + Write an 8 bit value to an I/O port and save it to the S3 script + + @param Port IO Port + @param Data Data in IO Port + + @retval None. + +**/ +VOID +ScriptWriteIo8 ( + UINT16 Port, + UINT8 Data + ) +{ + mCpuIo->Io.Write ( + mCpuIo, + EfiCpuIoWidthUint8, + Port, + 1, + &Data + ); + +} + +/** + + Read the refresh bit from the REFRESH_PORT + + @param None. + + @retval Refresh bit. + +**/ +UINT8 +ReadRefresh ( + VOID + ) +{ + UINT8 Data; + + mCpuIo->Io.Read ( + mCpuIo, + EfiCpuIoWidthUint8, + REFRESH_PORT, + 1, + &Data + ); + return (UINT8) (Data & REFRESH_ON); +} + +/** + + Waits for the TickNumber of ticks from a known platform time source. + + @param This Pointer to the protocol instance. + @param TickNumber Tick Number to be waited + + + @retval EFI_SUCCESS If number of ticks occurred. + @retval EFI_NOT_FOUND Could not locate CPU IO protocol + +**/ +EFI_STATUS +EFIAPI +WaitForTick ( + IN EFI_METRONOME_ARCH_PROTOCOL *This, + IN UINT32 TickNumber + ) +{ + // + // Wait for TickNumber toggles of the Refresh bit + // + for (; TickNumber != 0x00; TickNumber--) { + while (ReadRefresh () == REFRESH_ON) + ; + while (ReadRefresh () == REFRESH_OFF) + ; + } + + return EFI_SUCCESS; +} + +// +// Driver Entry Point +// +/** + Install the LegacyMetronome driver. Loads a Metronome Arch Protocol based + on the Port 61 timer. + + @param ImageHandle Handle for the image of this driver + @param SystemTable Pointer to the EFI System Table + + @retval EFI_SUCCESS Metronome Architectural Protocol Installed + +**/ +EFI_STATUS +EFIAPI +InstallLegacyMetronome ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Make sure the Metronome Architectural Protocol is not already installed in the system + // + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiMetronomeArchProtocolGuid); + + // + // Get the CPU I/O Protocol that this driver requires + // If the CPU I/O Protocol is not found, then ASSERT because the dependency expression + // should guarantee that it is present in the handle database. + // + Status = gBS->LocateProtocol ( + &gEfiCpuIoProtocolGuid, + NULL, + (void **)&mCpuIo + ); + ASSERT_EFI_ERROR (Status); + + // + // Program port 61 timer 1 as refresh timer. We could use ACPI timer in the + // future. + // + ScriptWriteIo8 (TIMER1_CONTROL_PORT, LOAD_COUNTER1_LSB); + ScriptWriteIo8 (TIMER1_COUNT_PORT, COUNTER1_COUNT); + + // + // Install on a new handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mMetronomeHandle, + &gEfiMetronomeArchProtocolGuid, + &mMetronome, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Vlv2TbltDevicePkg/Metronome/LegacyMetronome.h b/Vlv2TbltDevicePkg/Metronome/LegacyMetronome.h new file mode 100644 index 0000000000..b9c32da1f2 --- /dev/null +++ b/Vlv2TbltDevicePkg/Metronome/LegacyMetronome.h @@ -0,0 +1,69 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + LegacyMetronome.h + +Abstract: + + Driver implementing the EFI 2.0 metronome protocol using the legacy PORT 61 + timer. + +--*/ + +#ifndef _LEGACY_METRONOME_H +#define _LEGACY_METRONOME_H + +// +// Statements that include other files +// +#include "Protocol/Metronome.h" +#include "Protocol/CpuIo.h" +#include "Library/DebugLib.h" +#include "Library/UefiBootServicesTableLib.h" + + +// +// Private definitions +// +#define TICK_PERIOD 300 +#define REFRESH_PORT 0x61 +#define REFRESH_ON 0x10 +#define REFRESH_OFF 0x00 +#define TIMER1_CONTROL_PORT 0x43 +#define TIMER1_COUNT_PORT 0x41 +#define LOAD_COUNTER1_LSB 0x54 +#define COUNTER1_COUNT 0x12 + +// +// Function Prototypes +// +/** + Waits for the TickNumber of ticks from a known platform time source. + + @param This Pointer to the protocol instance. + @param TickNumber Tick Number to be waited + + @retval EFI_SUCCESS If number of ticks occurred. + @retval EFI_NOT_FOUND Could not locate CPU IO protocol + +**/ +EFI_STATUS +EFIAPI +WaitForTick ( + IN EFI_METRONOME_ARCH_PROTOCOL *This, + IN UINT32 TickNumber + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Metronome/Metronome.inf b/Vlv2TbltDevicePkg/Metronome/Metronome.inf new file mode 100644 index 0000000000..85237bd986 --- /dev/null +++ b/Vlv2TbltDevicePkg/Metronome/Metronome.inf @@ -0,0 +1,54 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# + +# Module Name: +# +# LegacyMetronome.inf +# +# Abstract: +# +# Component description file for LegacyMetronome module +# +#--*/ +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = LegacyMetronome + FILE_GUID = 07A9330A-F347-11d4-9A49-0090273FC14D + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InstallLegacyMetronome + +[sources.common] + LegacyMetronome.c + LegacyMetronome.h + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + DevicePathLib + UefiLib + +[Protocols] + +gEfiMetronomeArchProtocolGuid +gEfiCpuIoProtocolGuid + +[Depex] +gEfiCpuIoProtocolGuid AND gEfiBootScriptSaveProtocolGuid + + diff --git a/Vlv2TbltDevicePkg/MonoStatusCode/EfiStatusCode.h b/Vlv2TbltDevicePkg/MonoStatusCode/EfiStatusCode.h new file mode 100644 index 0000000000..a18fef233a --- /dev/null +++ b/Vlv2TbltDevicePkg/MonoStatusCode/EfiStatusCode.h @@ -0,0 +1,183 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + EfiStatusCode.h + +Abstract: + + Status Code Definitions, according to Intel Platform Innovation Framework + for EFI Status Codes Specification + Revision 0.92 + + The file is divided into sections for ease of use. + + Section: Contents: + 1 General Status Code Definitions + 2 Class definitions + 3 Computing Unit Subclasses, Progress and Error Codes + 4 Peripheral Subclasses, Progress and Error Codes. + 5 IO Bus Subclasses, Progress and Error Codes. + 6 Software Subclasses, Progress and Error Codes. + 7 Debug Codes + +--*/ + +#ifndef _EFI_STATUS_CODE_H_ +#define _EFI_STATUS_CODE_H_ + + + +#define EFI_SW_PEIM_EC_NO_RECOVERY_CAPSULE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_PEIM_EC_INVALID_CAPSULE_DESCRIPTOR (EFI_SUBCLASS_SPECIFIC | 0x00000001) + + + +#define EFI_SW_PEIM_PC_RECOVERY_BEGIN (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_PEIM_PC_CAPSULE_LOAD (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_PEIM_PC_CAPSULE_START (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_PEIM_PC_RECOVERY_USER (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_PEIM_PC_RECOVERY_AUTO (EFI_SUBCLASS_SPECIFIC | 0x00000004) + + + +#define EFI_CU_MEMORY_PC_SPD_READ (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_MEMORY_PC_PRESENCE_DETECT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_MEMORY_PC_TIMING (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_CU_MEMORY_PC_CONFIGURING (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_CU_MEMORY_PC_OPTIMIZING (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_CU_MEMORY_PC_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_CU_MEMORY_PC_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_CU_MEMORY_PC_COMPLETE (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_CU_MEMORY_PC_INIT_BEGIN (EFI_SUBCLASS_SPECIFIC | 0x00000008) + + +#define EFI_DC_UNSPECIFIED 0x0 + +// +// CPU PEI +// +#define EFI_CU_HP_PC_PEI_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000010) +#define EFI_CU_HP_PC_PEI_STEP1 (EFI_SUBCLASS_SPECIFIC | 0x00000011) +#define EFI_CU_HP_PC_PEI_STEP2 (EFI_SUBCLASS_SPECIFIC | 0x00000012) +#define EFI_CU_HP_PC_PEI_STEP3 (EFI_SUBCLASS_SPECIFIC | 0x00000013) +#define EFI_CU_HP_PC_PEI_STEP4 (EFI_SUBCLASS_SPECIFIC | 0x00000014) +#define EFI_CU_HP_PC_PEI_STEP5 (EFI_SUBCLASS_SPECIFIC | 0x00000015) +#define EFI_CU_HP_PC_PEI_STEP6 (EFI_SUBCLASS_SPECIFIC | 0x00000016) +#define EFI_CU_HP_PC_PEI_STEP7 (EFI_SUBCLASS_SPECIFIC | 0x00000017) +#define EFI_CU_HP_PC_PEI_STEP8 (EFI_SUBCLASS_SPECIFIC | 0x00000018) +#define EFI_CU_HP_PC_PEI_STEP9 (EFI_SUBCLASS_SPECIFIC | 0x00000019) +#define EFI_CU_HP_PC_PEI_STEP10 (EFI_SUBCLASS_SPECIFIC | 0x0000001A) +#define EFI_CU_HP_PC_PEI_STEP11 (EFI_SUBCLASS_SPECIFIC | 0x0000001B) +#define EFI_CU_HP_PC_PEI_STEP12 (EFI_SUBCLASS_SPECIFIC | 0x0000001C) +#define EFI_CU_HP_PC_PEI_STEP13 (EFI_SUBCLASS_SPECIFIC | 0x0000001D) +#define EFI_CU_HP_PC_PEI_STEP14 (EFI_SUBCLASS_SPECIFIC | 0x0000001E) +#define EFI_CU_HP_PC_PEI_END (EFI_SUBCLASS_SPECIFIC | 0x0000001F) + +// +// CPU DXE +// +#define EFI_CU_HP_PC_DXE_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000020) +#define EFI_CU_HP_PC_DXE_STEP1 (EFI_SUBCLASS_SPECIFIC | 0x00000021) +#define EFI_CU_HP_PC_DXE_STEP2 (EFI_SUBCLASS_SPECIFIC | 0x00000022) +#define EFI_CU_HP_PC_DXE_STEP3 (EFI_SUBCLASS_SPECIFIC | 0x00000023) +#define EFI_CU_HP_PC_DXE_STEP4 (EFI_SUBCLASS_SPECIFIC | 0x00000024) +#define EFI_CU_HP_PC_DXE_STEP5 (EFI_SUBCLASS_SPECIFIC | 0x00000025) +#define EFI_CU_HP_PC_DXE_STEP6 (EFI_SUBCLASS_SPECIFIC | 0x00000026) +#define EFI_CU_HP_PC_DXE_STEP7 (EFI_SUBCLASS_SPECIFIC | 0x00000027) +#define EFI_CU_HP_PC_DXE_STEP8 (EFI_SUBCLASS_SPECIFIC | 0x00000028) +#define EFI_CU_HP_PC_DXE_STEP9 (EFI_SUBCLASS_SPECIFIC | 0x00000029) +#define EFI_CU_HP_PC_DXE_STEP10 (EFI_SUBCLASS_SPECIFIC | 0x0000002A) +#define EFI_CU_HP_PC_DXE_STEP11 (EFI_SUBCLASS_SPECIFIC | 0x0000002B) +#define EFI_CU_HP_PC_DXE_STEP12 (EFI_SUBCLASS_SPECIFIC | 0x0000002C) +#define EFI_CU_HP_PC_DXE_STEP13 (EFI_SUBCLASS_SPECIFIC | 0x0000002D) +#define EFI_CU_HP_PC_DXE_STEP14 (EFI_SUBCLASS_SPECIFIC | 0x0000002E) +#define EFI_CU_HP_PC_DXE_END (EFI_SUBCLASS_SPECIFIC | 0x0000002F) + +// +// CPU SMM PEI +// +#define EFI_CU_HP_PC_SMM_PEI_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000030) +#define EFI_CU_HP_PC_SMM_PEI_STEP1 (EFI_SUBCLASS_SPECIFIC | 0x00000031) +#define EFI_CU_HP_PC_SMM_PEI_STEP2 (EFI_SUBCLASS_SPECIFIC | 0x00000032) +#define EFI_CU_HP_PC_SMM_PEI_STEP3 (EFI_SUBCLASS_SPECIFIC | 0x00000033) +#define EFI_CU_HP_PC_SMM_PEI_STEP4 (EFI_SUBCLASS_SPECIFIC | 0x00000034) +#define EFI_CU_HP_PC_SMM_PEI_STEP5 (EFI_SUBCLASS_SPECIFIC | 0x00000035) +#define EFI_CU_HP_PC_SMM_PEI_STEP6 (EFI_SUBCLASS_SPECIFIC | 0x00000036) +#define EFI_CU_HP_PC_SMM_PEI_END (EFI_SUBCLASS_SPECIFIC | 0x0000003F) + +// +// CPU SMM DXE +// +#define EFI_CU_HP_PC_SMM_DXE_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000040) +#define EFI_CU_HP_PC_SMM_DXE_STEP1 (EFI_SUBCLASS_SPECIFIC | 0x00000041) +#define EFI_CU_HP_PC_SMM_DXE_STEP2 (EFI_SUBCLASS_SPECIFIC | 0x00000042) +#define EFI_CU_HP_PC_SMM_DXE_STEP3 (EFI_SUBCLASS_SPECIFIC | 0x00000043) +#define EFI_CU_HP_PC_SMM_DXE_STEP4 (EFI_SUBCLASS_SPECIFIC | 0x00000044) +#define EFI_CU_HP_PC_SMM_DXE_STEP5 (EFI_SUBCLASS_SPECIFIC | 0x00000045) +#define EFI_CU_HP_PC_SMM_DXE_STEP6 (EFI_SUBCLASS_SPECIFIC | 0x00000046) +#define EFI_CU_HP_PC_SMM_DXE_END (EFI_SUBCLASS_SPECIFIC | 0x0000004F) + +// +// PEI before memory initialization +// +#define EFI_CU_PLATFORM_PEI_INIT (EFI_OEM_SPECIFIC | 0x00000001) +#define EFI_CU_PLATFORM_PEI_STEP1 (EFI_OEM_SPECIFIC | 0x00000002) +#define EFI_CU_PLATFORM_PEI_STEP2 (EFI_OEM_SPECIFIC | 0x00000003) +#define EFI_CU_PLATFORM_PEI_STEP3 (EFI_OEM_SPECIFIC | 0x00000004) +#define EFI_CU_PLATFORM_PEI_STEP4 (EFI_OEM_SPECIFIC | 0x00000005) +#define EFI_CU_SMBUS_PEI_INIT (EFI_OEM_SPECIFIC | 0x00000006) +#define EFI_CU_SMBUS_PEI_EXEC_ENTRY (EFI_OEM_SPECIFIC | 0x00000007) +#define EFI_CU_SMBUS_PEI_EXEC_EXIT (EFI_OEM_SPECIFIC | 0x00000008) +#define EFI_CU_CLOCK_PEI_INIT_ENTRY (EFI_OEM_SPECIFIC | 0x00000009) +#define EFI_CU_CLOCK_PEI_INIT_EXIT (EFI_OEM_SPECIFIC | 0x0000000A) +#define EFI_CU_MEMORY_PC_PROG_MTRR (EFI_OEM_SPECIFIC | 0x0000000B) +#define EFI_CU_MEMORY_PC_PROG_MTRR_END (EFI_OEM_SPECIFIC | 0x0000000C) +#define EFI_CU_PLATFORM_PEI_STEP12 (EFI_OEM_SPECIFIC | 0x0000000D) +#define EFI_CU_PLATFORM_PEI_STEP13 (EFI_OEM_SPECIFIC | 0x0000000E) +#define EFI_CU_PLATFORM_PEI_END (EFI_OEM_SPECIFIC | 0x0000000F) + +#define EFI_CU_PLATFORM_DXE_INIT (EFI_OEM_SPECIFIC | 0x00000011) +#define EFI_CU_PLATFORM_DXE_STEP1 (EFI_OEM_SPECIFIC | 0x00000012) +#define EFI_CU_PLATFORM_DXE_STEP2 (EFI_OEM_SPECIFIC | 0x00000013) +#define EFI_CU_PLATFORM_DXE_STEP3 (EFI_OEM_SPECIFIC | 0x00000014) +#define EFI_CU_PLATFORM_DXE_STEP4 (EFI_OEM_SPECIFIC | 0x00000015) +#define EFI_CU_PLATFORM_DXE_INIT_DONE (EFI_OEM_SPECIFIC | 0x00000016) + +#define EFI_CU_OVERCLOCK_PEI_INIT_ENTRY (EFI_OEM_SPECIFIC | 0x00000017) +#define EFI_CU_OVERCLOCK_PEI_INIT_EXIT (EFI_OEM_SPECIFIC | 0x00000018) + +// +// BDS +// +#define EFI_CU_BDS_INIT (EFI_OEM_SPECIFIC | 0x00000060) +#define EFI_CU_BDS_STEP1 (EFI_OEM_SPECIFIC | 0x00000061) +#define EFI_CU_BDS_STEP2 (EFI_OEM_SPECIFIC | 0x00000062) +#define EFI_CU_BDS_STEP3 (EFI_OEM_SPECIFIC | 0x00000063) +#define EFI_CU_BDS_STEP4 (EFI_OEM_SPECIFIC | 0x00000064) +#define EFI_CU_BDS_STEP5 (EFI_OEM_SPECIFIC | 0x00000065) +#define EFI_CU_BDS_STEP6 (EFI_OEM_SPECIFIC | 0x00000066) +#define EFI_CU_BDS_STEP7 (EFI_OEM_SPECIFIC | 0x00000067) +#define EFI_CU_BDS_STEP8 (EFI_OEM_SPECIFIC | 0x00000068) +#define EFI_CU_BDS_STEP9 (EFI_OEM_SPECIFIC | 0x00000069) +#define EFI_CU_BDS_STEP10 (EFI_OEM_SPECIFIC | 0x0000006A) +#define EFI_CU_BDS_STEP11 (EFI_OEM_SPECIFIC | 0x0000006B) +#define EFI_CU_BDS_STEP12 (EFI_OEM_SPECIFIC | 0x0000006C) +#define EFI_CU_BDS_STEP13 (EFI_OEM_SPECIFIC | 0x0000006D) +#define EFI_CU_BDS_STEP14 (EFI_OEM_SPECIFIC | 0x0000006E) +#define EFI_CU_BDS_END (EFI_OEM_SPECIFIC | 0x0000006F) + + + +#endif diff --git a/Vlv2TbltDevicePkg/MonoStatusCode/MonoStatusCode.c b/Vlv2TbltDevicePkg/MonoStatusCode/MonoStatusCode.c new file mode 100644 index 0000000000..80a05b9bd1 --- /dev/null +++ b/Vlv2TbltDevicePkg/MonoStatusCode/MonoStatusCode.c @@ -0,0 +1,137 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + MonoStatusCode.c + +Abstract: + + PEIM to provide the status code functionality, to aid in system debug. + It includes output to 0x80 port and/or to serial port. + This PEIM is monolithic. Different platform should provide different library. + +--*/ + +#include "MonoStatusCode.h" +#include "PlatformStatusCode.h" +#define CMOS_EFI_DEBUG 0x14 + +// +// Module globals +// +EFI_PEI_PROGRESS_CODE_PPI mStatusCodePpi = { PlatformReportStatusCode }; + +EFI_PEI_PPI_DESCRIPTOR mPpiListStatusCode = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiStatusCodePpiGuid, + &mStatusCodePpi +}; + +// +// Function implemenations +// + +/** + Translate from a DXE status code interface into a PEI-callable + interface, making the PEI the least common denominator.. + + Same as DXE ReportStatusCode RT service + + +**/ +EFI_STATUS +EFIAPI +TranslateDxeStatusCodeToPeiStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +{ + return PlatformReportStatusCode (NULL, CodeType, Value, Instance, CallerId, Data); +} + +/** + Build a hob describing the status code listener that has been installed. + This will be used by DXE code until a runtime status code listener is + installed. + + @param PeiServices General purpose services available to every PEIM. + + @retval Status EFI_SUCCESS if the interface could be successfully + installed + +**/ +EFI_STATUS +EFIAPI +InitializeDxeReportStatusCode ( + IN const EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status = EFI_UNSUPPORTED; + + VOID *Instance; + + VOID *Result; + + Instance = (VOID *) (UINTN) TranslateDxeStatusCodeToPeiStatusCode; + + Result = BuildGuidDataHob ( + &gEfiStatusCodeRuntimeProtocolGuid, + &Instance, + sizeof (VOID *) + ); + if (Result != NULL) { + Status = EFI_SUCCESS; + } + return Status; +} + +/** + Initialize the platform status codes and publish the platform status code + PPI. + + @param FfsHeader FV this PEIM was loaded from. + @param PeiServices General purpose services available to every PEIM. + + @retval Status EFI_SUCCESS + +**/ +VOID +EFIAPI +InitializeMonoStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + // + // Initialize status code listeners. + // + PlatformInitializeStatusCode (FfsHeader, PeiServices); + + // + // Publish the status code capability to other modules + // + Status = (*PeiServices)->InstallPpi (PeiServices, &mPpiListStatusCode); + + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_ERROR, "\nMono Status Code PEIM Loaded\n")); + + return ; +} diff --git a/Vlv2TbltDevicePkg/MonoStatusCode/MonoStatusCode.h b/Vlv2TbltDevicePkg/MonoStatusCode/MonoStatusCode.h new file mode 100644 index 0000000000..65fd3deda4 --- /dev/null +++ b/Vlv2TbltDevicePkg/MonoStatusCode/MonoStatusCode.h @@ -0,0 +1,133 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + MonoStatusCode.h + +Abstract: + + Monolithic single PEIM to provide the status code functionality. + The PEIM is a blend of libraries that correspond to the different status code + listeners that a platform installs. + +--*/ + +#ifndef _MONO_STATUS_CODE_H_ +#define _MONO_STATUS_CODE_H_ + +// +// Statements that include other files. +// +#include "PiPei.h" + +#include "Pi/PiBootMode.h" + +#include "Ppi/StatusCode.h" +#include "Ppi/MemoryDiscovered.h" +#include "Ppi/FvLoadFile.h" + +#include "Library/HobLib.h" +#include "Library/DebugLib.h" +#include "Library/IoLib.h" +#include "Library/SerialPortLib.h" +#include "Protocol/StatusCode.h" + + +#ifndef _STATUS_CODE_ENABLER_H_ +#define _STATUS_CODE_ENABLER_H_ + +#ifdef EFI_DEBUG + +#define EFI_STATUS_CODE_ENABLER_HOB_GUID \ + { \ + 0x5ffc6cf3, 0x71ad, 0x46f5, 0xbd, 0x8b, 0x7e, 0x8f, 0xfe, 0x19, 0x7, 0xd7 \ + } + +extern EFI_GUID gEfiSerialStatusCodeEnablerHobGuid; + +typedef struct _EFI_STATUS_CODE_INFO { + BOOLEAN StatusCodeDisable; +} EFI_STATUS_CODE_INFO; + +#endif +#endif + + + +// +// Platform specific function Declarations. These must be implemented in a +// subdirectory named PlatformName in a file named PlatformStatusCode.c. +// + +// +// This is the platform function to initialize the listeners desired by the +// platform. +// +VOID +PlatformInitializeStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +// +// This is the platform function that calls all of the listeners desired by the +// platform. +// +EFI_STATUS +EFIAPI +PlatformReportStatusCode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID * CallerId, + IN CONST EFI_STATUS_CODE_DATA * Data OPTIONAL + ); + +// +// Platform independent function Declarations +// +// +// Initialize the status code listeners and publish the status code PPI. +// +VOID +EFIAPI +InitializeMonoStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN const EFI_PEI_SERVICES **PeiServices + ); + +// +// Convert a DXE status code call into a PEI status code call. +// +EFI_STATUS +EFIAPI +TranslateDxeStatusCodeToPeiStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ); + +// +// Publish a HOB that contains the listener to be used by DXE. +// +EFI_STATUS +EFIAPI +InitializeDxeReportStatusCode ( + IN const EFI_PEI_SERVICES **PeiServices + ); + +#endif diff --git a/Vlv2TbltDevicePkg/MonoStatusCode/MonoStatusCode.inf b/Vlv2TbltDevicePkg/MonoStatusCode/MonoStatusCode.inf new file mode 100644 index 0000000000..d16c04d83f --- /dev/null +++ b/Vlv2TbltDevicePkg/MonoStatusCode/MonoStatusCode.inf @@ -0,0 +1,78 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# Module Name: +# +# MonoStatusCode.inf +# +# Abstract: +# +# Component description file for Status Code PEI module +# +#--*/ + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = MonoStatusCode + FILE_GUID = 4BB346D2-8076-4671-8BC9-7B95CBB9A6DF + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 +# ENTRY_POINT = InstallMonoStatusCode + LIBRARY_CLASS = MonoStatusCodeLib + +[sources.common] + MonoStatusCode.c + MonoStatusCode.h + PlatformStatusCode.c + PlatformStatusCode.h + PeiPostCode.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IA32FamilyCpuPkg/IA32FamilyCpuPkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +[LibraryClasses] + PeimEntryPoint + HobLib + DebugLib + SerialPortLib + ReportStatusCodeLib + PrintLib + BaseMemoryLib + PchPlatformLib + +[Ppis] + gEfiPeiMemoryDiscoveredPpiGuid + gEfiPeiStatusCodePpiGuid + gEfiPeiFvFileLoaderPpiGuid + +[Protocols] + gEfiStatusCodeRuntimeProtocolGuid + +[Pcd] + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseRam + +[Guids] + gEfiPlatformCpuInfoGuid + gEfiHtBistHobGuid + gEfiStatusCodeDataTypeStringGuid ## CONSUMES + +[Depex] + TRUE + + + diff --git a/Vlv2TbltDevicePkg/MonoStatusCode/PeiPostCode.c b/Vlv2TbltDevicePkg/MonoStatusCode/PeiPostCode.c new file mode 100644 index 0000000000..b73026733b --- /dev/null +++ b/Vlv2TbltDevicePkg/MonoStatusCode/PeiPostCode.c @@ -0,0 +1,126 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + PeiPostCode.c + +Abstract: + + Worker functions for PostCode + +--*/ + +#include "EfiStatusCode.h" + +#pragma pack(1) +typedef struct { + EFI_STATUS_CODE_VALUE StatusValue; + UINT8 Port80Value; +} EFI_STATUS_CODE_TO_PORT_80; +#pragma pack() + +// +// see Edk\Foundation\Library\EfiCommonLib\PostCode.c for DXE/BDS POST codes. +// +EFI_STATUS_CODE_TO_PORT_80 mPeiPort80Table[] = { + // + // Platform init + // + {EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_PLATFORM_PEI_INIT, 0x11}, + {EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_PLATFORM_PEI_STEP1, 0x12}, + {EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_PLATFORM_PEI_STEP2, 0x13}, + {EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_PLATFORM_PEI_STEP3, 0x14}, + {EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_PLATFORM_PEI_STEP4, 0x15}, + + // + // SMBUS + // + {EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_SMBUS_PEI_INIT, 0x16}, + {EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_SMBUS_PEI_EXEC_ENTRY, 0x17}, + {EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_SMBUS_PEI_EXEC_EXIT, 0x18}, + + // + // Clock + // + {EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_CLOCK_PEI_INIT_ENTRY, 0x19}, + {EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_CLOCK_PEI_INIT_EXIT, 0x1A}, + + // + // Over clocking support + // + {EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_OVERCLOCK_PEI_INIT_ENTRY, 0x1B}, + {EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_OVERCLOCK_PEI_INIT_EXIT, 0x1C}, + + // + // MRC + // + {EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_INIT_BEGIN, 0x21}, + {EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_SPD_READ, 0x23}, + {EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_PRESENCE_DETECT, 0x24}, + {EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_TIMING, 0x25}, + {EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_OPTIMIZING, 0x26}, + {EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_CONFIGURING, 0x27}, + {EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_TEST, 0x28}, + {EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_COMPLETE, 0x29}, + + // + // Platform Init after MRC + // + {EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_PROG_MTRR, 0x2A}, + {EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_PROG_MTRR_END, 0x2B}, + + {EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_PC_RECOVERY_BEGIN, 0x31}, + {EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_PC_RECOVERY_AUTO, 0x32}, + {EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_PC_CAPSULE_LOAD, 0x33}, + {EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_PC_CAPSULE_START, 0x34}, + {EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_EC_NO_RECOVERY_CAPSULE, 0x35}, + + {EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_PEI_INIT, 0x41}, + {EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_PEI_STEP1, 0x42}, + {EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_PEI_END, 0x43}, + {EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_SMM_PEI_INIT, 0x44}, + {EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_SMM_PEI_STEP1, 0x45}, + {EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_SMM_PEI_END, 0x46} +}; + +BOOLEAN +PeiCodeTypeToPostCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + OUT UINT8 *PostCode + ) +{ + UINTN Index; + + if (CodeType == EFI_PROGRESS_CODE) { + if ((Value == (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN)) || + (Value == (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END)) || + (Value == (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN)) || + (Value == (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END))) { + return FALSE; + } + } else { + return FALSE; + } + + for (Index = 0; Index < sizeof(mPeiPort80Table)/sizeof(EFI_STATUS_CODE_TO_PORT_80); Index++) { + if (mPeiPort80Table[Index].StatusValue == Value) { + *PostCode = mPeiPort80Table[Index].Port80Value; + return TRUE; + } + } + + return FALSE; +} diff --git a/Vlv2TbltDevicePkg/MonoStatusCode/PlatformStatusCode.c b/Vlv2TbltDevicePkg/MonoStatusCode/PlatformStatusCode.c new file mode 100644 index 0000000000..3927cda059 --- /dev/null +++ b/Vlv2TbltDevicePkg/MonoStatusCode/PlatformStatusCode.c @@ -0,0 +1,386 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + PlatformStatusCode.c + +Abstract: + + Contains Platform specific implementations required to use status codes. + +--*/ + +#include "PlatformStatusCode.h" +#include +#include +#include +#include + +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_HANDLE Handle; +} PEIM_FILE_HANDLE_EXTENDED_DATA; + +#define CONFIG_PORT0 0x4E +#define PCI_IDX 0xCF8 +#define PCI_DAT 0xCFC + +#define PCI_LPC_BASE (0x8000F800) +#define PCI_LPC_REG(x) (PCI_LPC_BASE + (x)) + +// +// Function implementations +// +BOOLEAN +PeiCodeTypeToPostCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + OUT UINT8 *PostCode + ); + +/** + Provide a port 80 status code + + @param Same as ReportStatusCode PPI + + @retval EFI_SUCCESS Always returns success. + +**/ +EFI_STATUS +EFIAPI +Port80ReportStatusCode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL + ) + +{ + EFI_STATUS Status; + EFI_FV_FILE_INFO FvFileInfo; + UINT16 Port80Code = 0; + + // + // Progress or error code, Output Port 80h card. + // + if (!PeiCodeTypeToPostCode (CodeType, Value, (UINT8 *)&Port80Code)) { + if ((Data != NULL) && (Value ==(EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN))){ + Status = PeiServicesFfsGetFileInfo ( + ((PEIM_FILE_HANDLE_EXTENDED_DATA *) (Data + 1))->Handle, + &FvFileInfo + ); + if (!EFI_ERROR (Status)) { + Port80Code = (FvFileInfo.FileName.Data4[6]<<8) + (FvFileInfo.FileName.Data4[7]); + } + } + } + if (Port80Code != 0){ + IoWrite16 (0x80, (UINT16) Port80Code); + DEBUG ((EFI_D_ERROR, "POSTCODE=<%04x>\n", Port80Code)); + } + return EFI_SUCCESS; +} + +/** + Provide a serial status code + + @param Same as ReportStatusCode PPI + + @retval EFI_SUCCESS Always returns success. + +**/ +EFI_STATUS +EFIAPI +SerialReportStatusCode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID * CallerId, + IN CONST EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +{ + CHAR8 *Filename; + CHAR8 *Description; + CHAR8 *Format; + CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE]; + UINT32 ErrorLevel; + UINT32 LineNumber; + UINTN CharCount; + BASE_LIST Marker; + + Buffer[0] = '\0'; + + if (Data != NULL && + ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) { + // + // Print ASSERT() information into output buffer. + // + CharCount = AsciiSPrint ( + Buffer, + sizeof (Buffer), + "\n\rPEI_ASSERT!: %a (%d): %a\n\r", + Filename, + LineNumber, + Description + ); + } else if (Data != NULL && + ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { + // + // Print DEBUG() information into output buffer. + // + CharCount = AsciiBSPrint ( + Buffer, + sizeof (Buffer), + Format, + Marker + ); + } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { + // + // Print ERROR information into output buffer. + // + CharCount = AsciiSPrint ( + Buffer, + sizeof (Buffer), + "ERROR: C%x:V%x I%x", + CodeType, + Value, + Instance + ); + + ASSERT(CharCount > 0); + + if (CallerId != NULL) { + CharCount += AsciiSPrint ( + &Buffer[CharCount], + (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)), + " %g", + CallerId + ); + } + + if (Data != NULL) { + CharCount += AsciiSPrint ( + &Buffer[CharCount], + (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)), + " %x", + Data + ); + } + + CharCount += AsciiSPrint ( + &Buffer[CharCount], + (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)), + "\n\r" + ); + } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) { + // + // Print PROGRESS information into output buffer. + // + CharCount = AsciiSPrint ( + Buffer, + sizeof (Buffer), + "PROGRESS CODE: V%x I%x\n\r", + Value, + Instance + ); + } else if (Data != NULL && + CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeStringGuid) && + ((EFI_STATUS_CODE_STRING_DATA *) Data)->StringType == EfiStringAscii) { + // + // EFI_STATUS_CODE_STRING_DATA + // + CharCount = AsciiSPrint ( + Buffer, + sizeof (Buffer), + "%a\n\r", + ((EFI_STATUS_CODE_STRING_DATA *) Data)->String.Ascii + ); + } else { + // + // Code type is not defined. + // + CharCount = AsciiSPrint ( + Buffer, + sizeof (Buffer), + "Undefined: C%x:V%x I%x\n\r", + CodeType, + Value, + Instance + ); + } + + // + // Call SerialPort Lib function to do print. + // + SerialPortWrite ((UINT8 *) Buffer, CharCount); + + return EFI_SUCCESS; +} + +/** + + Call all status code listeners in the MonoStatusCode. + + @param PeiServices The PEI core services table. + @param CodeType Type of Status Code. + @param Value Value to output for Status Code. + @param Instance Instance Number of this status code. + @param CallerId ID of the caller of this status code. + @param Data Optional data associated with this status code. + + @retval EFI_SUCCESS If status code is successfully reported. + @retval EFI_NOT_AVAILABLE_YET If StatusCodePpi has not been installed. + +**/ +EFI_STATUS +EFIAPI +PlatformReportStatusCode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID * CallerId, + IN CONST EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +{ + // + // If we are in debug mode, we will allow serial status codes + // + SerialReportStatusCode (PeiServices, CodeType, Value, Instance, CallerId, Data); + + Port80ReportStatusCode (PeiServices, CodeType, Value, Instance, CallerId, Data); + + return EFI_SUCCESS; +} + +/** + Install the PEIM. Initialize listeners, publish the PPI and HOB for PEI and + DXE use respectively. + + @param FfsHeader FV this PEIM was loaded from. + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS The function always returns success. + +**/ +EFI_STATUS +EFIAPI +InstallMonoStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + + // + // Initialize all listeners + // + InitializeMonoStatusCode (FfsHeader, PeiServices); + + // + // Publish the listener in a HOB for DXE use. + // + InitializeDxeReportStatusCode (PeiServices); + + return EFI_SUCCESS; +} + +#define V_PCH_ILB_IRQE_UARTIRQEN_IRQ3 BIT3 // UART IRQ3 Enable +#define V_PCH_ILB_IRQE_UARTIRQEN_IRQ4 BIT4 // UART IRQ4 Enable +#define PCIEX_BASE_ADDRESS 0xE0000000 +#define PciD31F0RegBase PCIEX_BASE_ADDRESS + (UINT32) (31 << 15) +#define SB_RCBA 0xfed1c000 + +extern PCH_STEPPING EFIAPI PchStepping (VOID); + +VOID +RamDebugInit ( + VOID + ); + +/** + Enable legacy decoding on ICH6 + + @param none + + @retval EFI_SUCCESS Always returns success. + +**/ +EFI_STATUS +EnableInternalUart( + VOID + ) +{ + + // + // Program and enable PMC Base. + // + IoWrite32 (PCI_IDX, PCI_LPC_REG(R_PCH_LPC_PMC_BASE)); + IoWrite32 (PCI_DAT, (PMC_BASE_ADDRESS | B_PCH_LPC_PMC_BASE_EN)); + + // + // Enable COM1 for debug message output. + // + MmioAndThenOr32 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, (UINT32) (~(B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR + B_PCH_PMC_GEN_PMCON_PWROK_FLR)), BIT24); + + // + // Silicon Steppings + // + if (PchStepping()>= PchB0) + MmioOr8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) V_PCH_ILB_IRQE_UARTIRQEN_IRQ4); + else + MmioOr8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) V_PCH_ILB_IRQE_UARTIRQEN_IRQ3); + MmioAnd32(IO_BASE_ADDRESS + 0x0520, (UINT32)~(0x00000187)); + MmioOr32 (IO_BASE_ADDRESS + 0x0520, (UINT32)0x81); // UART3_RXD-L + MmioAnd32(IO_BASE_ADDRESS + 0x0530, (UINT32)~(0x00000007)); + MmioOr32 (IO_BASE_ADDRESS + 0x0530, (UINT32)0x1); // UART3_RXD-L + MmioOr8 (PciD31F0RegBase + R_PCH_LPC_UART_CTRL, (UINT8) B_PCH_LPC_UART_CTRL_COM1_EN); + + return EFI_SUCCESS; +} + +/** + INIT the SIO. Ported this code and I don't undertand the comments either. + + @param FfsHeader FV this PEIM was loaded from. + @param PeiServices General purpose services available to every PEIM. + + None + +**/ +VOID +EFIAPI +PlatformInitializeStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + + // + // Enable internal COM1 on South Cluster. + // + EnableInternalUart(); + + + // + // Initialize additional debug status code listeners. + // + SerialPortInitialize(); + +} +//#endif //EFI_DEBUG + diff --git a/Vlv2TbltDevicePkg/MonoStatusCode/PlatformStatusCode.h b/Vlv2TbltDevicePkg/MonoStatusCode/PlatformStatusCode.h new file mode 100644 index 0000000000..51e13e03de --- /dev/null +++ b/Vlv2TbltDevicePkg/MonoStatusCode/PlatformStatusCode.h @@ -0,0 +1,207 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + PlatformStatusCode.h + +Abstract: + + Contains Platform specific implementations required to use status codes. + +--*/ + +#ifndef _PLATFORM_STATUS_CODE_H_ +#define _PLATFORM_STATUS_CODE_H_ + + +#define CONFIG_PORT0 0x4E +#define INDEX_PORT0 0x4E +#define DATA_PORT0 0x4F +#define PCI_IDX 0xCF8 +#define PCI_DAT 0xCFC + +#include "MonoStatusCode.h" + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + + +Module Name: + + Port80StatusCodeLib.h + +Abstract: + + Lib to provide status code reporting via port 80. + +--*/ + +#ifndef _PEI_PORT_80_STATUS_CODE_H_ +#define _PEI_PORT_80_STATUS_CODE_H_ + + + +// +// Status code reporting function +// +EFI_STATUS +Port80ReportStatusCode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID * CallerId, + IN CONST EFI_STATUS_CODE_DATA * Data OPTIONAL + ); + +#endif + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + + +Module Name: + + SerialStatusCodeLib.h + +Abstract: + + Lib to provide Serial I/O status code reporting. + +--*/ + +#ifndef _PEI_SERIAL_STATUS_CODE_LIB_H_ +#define _PEI_SERIAL_STATUS_CODE_LIB_H_ + + +#include +#include +#include +#include +#include + +// +// Initialization function +// +VOID +SerialInitializeStatusCode ( + VOID + ); + +// +// Status code reporting function +// +EFI_STATUS +SerialReportStatusCode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID * CallerId, + IN CONST EFI_STATUS_CODE_DATA * Data OPTIONAL + ); + +#endif + +extern EFI_PEI_PROGRESS_CODE_PPI mStatusCodePpi; +extern EFI_PEI_PPI_DESCRIPTOR mPpiListStatusCode; +#define EFI_SIGNATURE_16(A, B) ((A) | (B << 8)) +#define EFI_SIGNATURE_32(A, B, C, D) (EFI_SIGNATURE_16 (A, B) | (EFI_SIGNATURE_16 (C, D) << 16)) +#define STATUSCODE_PEIM_SIGNATURE EFI_SIGNATURE_32 ('p', 's', 't', 'c') + +typedef struct { + UINT32 Signature; + EFI_FFS_FILE_HEADER *FfsHeader; + EFI_PEI_NOTIFY_DESCRIPTOR StatusCodeNotify; +} STATUSCODE_CALLBACK_STATE_INFORMATION; + +#pragma pack(1) +typedef struct { + UINT16 Limit; + UINT32 Base; +} GDT_DSCRIPTOR; +#pragma pack() + +#define STATUSCODE_PEIM_FROM_THIS(a) \ + BASE_CR ( \ + a, \ + STATUSCODE_CALLBACK_STATE_INFORMATION, \ + StatusCodeNotify \ + ) + +VOID +EFIAPI +PlatformInitializeStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + + +// +// Function declarations +// +/** + Install Firmware Volume Hob's once there is main memory + + @param PeiServices General purpose services available to every PEIM. + @param NotifyDescriptor Not Used + @param Ppi Not Used + + @retval Status EFI_SUCCESS if the interface could be successfully + installed + +**/ +EFI_STATUS +EFIAPI +MemoryDiscoveredPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c new file mode 100644 index 0000000000..b19550ff3e --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c @@ -0,0 +1,4310 @@ +/** @file + BDS Lib functions which relate with create or process the boot option. + +Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalBdsLib.h" +#include "String.h" + +BOOLEAN mEnumBootDevice = FALSE; +EFI_HII_HANDLE gBdsLibStringPackHandle = NULL; + +/** + The constructor function register UNI strings into imageHandle. + + It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor successfully added string package. + @retval Other value The constructor can't add string package. + +**/ +EFI_STATUS +EFIAPI +GenericBdsLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + gBdsLibStringPackHandle = HiiAddPackages ( + &gBdsLibStringPackageGuid, + ImageHandle, + GenericBdsLibStrings, + NULL + ); + + ASSERT (gBdsLibStringPackHandle != NULL); + + return EFI_SUCCESS; +} + +/** + Deletete the Boot Option from EFI Variable. The Boot Order Arrray + is also updated. + + @param OptionNumber The number of Boot option want to be deleted. + @param BootOrder The Boot Order array. + @param BootOrderSize The size of the Boot Order Array. + + @retval EFI_SUCCESS The Boot Option Variable was found and removed + @retval EFI_UNSUPPORTED The Boot Option Variable store was inaccessible + @retval EFI_NOT_FOUND The Boot Option Variable was not found +**/ +EFI_STATUS +EFIAPI +BdsDeleteBootOption ( + IN UINTN OptionNumber, + IN OUT UINT16 *BootOrder, + IN OUT UINTN *BootOrderSize + ) +{ + CHAR16 BootOption[9]; + UINTN Index; + EFI_STATUS Status; + + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber); + Status = gRT->SetVariable ( + BootOption, + &gEfiGlobalVariableGuid, + 0, + 0, + NULL + ); + + // + // adjust boot order array + // + for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) { + if (BootOrder[Index] == OptionNumber) { + CopyMem (&BootOrder[Index], &BootOrder[Index+1], *BootOrderSize - (Index+1) * sizeof (UINT16)); + *BootOrderSize -= sizeof (UINT16); + break; + } + } + + return Status; +} +/** + + Translate the first n characters of an Ascii string to + Unicode characters. The count n is indicated by parameter + Size. If Size is greater than the length of string, then + the entire string is translated. + + + @param AStr Pointer to input Ascii string. + @param Size The number of characters to translate. + @param UStr Pointer to output Unicode string buffer. + +**/ +VOID +AsciiToUnicodeSize ( + IN UINT8 *AStr, + IN UINTN Size, + OUT UINT16 *UStr + ) +{ + UINTN Idx; + + Idx = 0; + while (AStr[Idx] != 0) { + UStr[Idx] = (CHAR16) AStr[Idx]; + if (Idx == Size) { + break; + } + + Idx++; + } + UStr[Idx] = 0; +} + +/** + Build Legacy Device Name String according. + + @param CurBBSEntry BBS Table. + @param Index Index. + @param BufSize The buffer size. + @param BootString The output string. + +**/ +VOID +BdsBuildLegacyDevNameString ( + IN BBS_TABLE *CurBBSEntry, + IN UINTN Index, + IN UINTN BufSize, + OUT CHAR16 *BootString + ) +{ + CHAR16 *Fmt; + CHAR16 *Type; + UINT8 *StringDesc; + CHAR16 Temp[80]; + + switch (Index) { + // + // Primary Master + // + case 1: + Fmt = L"Primary Master %s"; + break; + + // + // Primary Slave + // + case 2: + Fmt = L"Primary Slave %s"; + break; + + // + // Secondary Master + // + case 3: + Fmt = L"Secondary Master %s"; + break; + + // + // Secondary Slave + // + case 4: + Fmt = L"Secondary Slave %s"; + break; + + default: + Fmt = L"%s"; + break; + } + + switch (CurBBSEntry->DeviceType) { + case BBS_FLOPPY: + Type = L"Floppy"; + break; + + case BBS_HARDDISK: + Type = L"Harddisk"; + break; + + case BBS_CDROM: + Type = L"CDROM"; + break; + + case BBS_PCMCIA: + Type = L"PCMCIAe"; + break; + + case BBS_USB: + Type = L"USB"; + break; + + case BBS_EMBED_NETWORK: + Type = L"Network"; + break; + + case BBS_BEV_DEVICE: + Type = L"BEVe"; + break; + + case BBS_UNKNOWN: + default: + Type = L"Unknown"; + break; + } + // + // If current BBS entry has its description then use it. + // + StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset); + if (NULL != StringDesc) { + // + // Only get fisrt 32 characters, this is suggested by BBS spec + // + AsciiToUnicodeSize (StringDesc, 32, Temp); + Fmt = L"%s"; + Type = Temp; + } + + // + // BbsTable 16 entries are for onboard IDE. + // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11 + // + if (Index >= 5 && Index <= 16 && (CurBBSEntry->DeviceType == BBS_HARDDISK || CurBBSEntry->DeviceType == BBS_CDROM)) { + Fmt = L"%s %d"; + UnicodeSPrint (BootString, BufSize, Fmt, Type, Index - 5); + } else { + UnicodeSPrint (BootString, BufSize, Fmt, Type); + } +} + +/** + + Create a legacy boot option for the specified entry of + BBS table, save it as variable, and append it to the boot + order list. + + + @param CurrentBbsEntry Pointer to current BBS table. + @param CurrentBbsDevPath Pointer to the Device Path Protocol instance of BBS + @param Index Index of the specified entry in BBS table. + @param BootOrderList On input, the original boot order list. + On output, the new boot order list attached with the + created node. + @param BootOrderListSize On input, the original size of boot order list. + On output, the size of new boot order list. + + @retval EFI_SUCCESS Boot Option successfully created. + @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory. + @retval Other Error occurs while setting variable. + +**/ +EFI_STATUS +BdsCreateLegacyBootOption ( + IN BBS_TABLE *CurrentBbsEntry, + IN EFI_DEVICE_PATH_PROTOCOL *CurrentBbsDevPath, + IN UINTN Index, + IN OUT UINT16 **BootOrderList, + IN OUT UINTN *BootOrderListSize + ) +{ + EFI_STATUS Status; + UINT16 CurrentBootOptionNo; + UINT16 BootString[10]; + CHAR16 BootDesc[100]; + CHAR8 HelpString[100]; + UINT16 *NewBootOrderList; + UINTN BufferSize; + UINTN StringLen; + VOID *Buffer; + UINT8 *Ptr; + UINT16 CurrentBbsDevPathSize; + UINTN BootOrderIndex; + UINTN BootOrderLastIndex; + UINTN ArrayIndex; + BOOLEAN IndexNotFound; + BBS_BBS_DEVICE_PATH *NewBbsDevPathNode; + + if ((*BootOrderList) == NULL) { + CurrentBootOptionNo = 0; + } else { + for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) { + IndexNotFound = TRUE; + for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) { + if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) { + IndexNotFound = FALSE; + break; + } + } + + if (!IndexNotFound) { + continue; + } else { + break; + } + } + + CurrentBootOptionNo = (UINT16) ArrayIndex; + } + + UnicodeSPrint ( + BootString, + sizeof (BootString), + L"Boot%04x", + CurrentBootOptionNo + ); + + BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc); + + // + // Create new BBS device path node with description string + // + UnicodeStrToAsciiStr (BootDesc, HelpString); + + StringLen = AsciiStrLen (HelpString); + NewBbsDevPathNode = AllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen); + if (NewBbsDevPathNode == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (NewBbsDevPathNode, CurrentBbsDevPath, sizeof (BBS_BBS_DEVICE_PATH)); + CopyMem (NewBbsDevPathNode->String, HelpString, StringLen + 1); + SetDevicePathNodeLength (&(NewBbsDevPathNode->Header), sizeof (BBS_BBS_DEVICE_PATH) + StringLen); + + // + // Create entire new CurrentBbsDevPath with end node + // + CurrentBbsDevPath = AppendDevicePathNode ( + NULL, + (EFI_DEVICE_PATH_PROTOCOL *) NewBbsDevPathNode + ); + if (CurrentBbsDevPath == NULL) { + FreePool (NewBbsDevPathNode); + return EFI_OUT_OF_RESOURCES; + } + + CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath)); + + BufferSize = sizeof (UINT32) + + sizeof (UINT16) + + StrSize (BootDesc) + + CurrentBbsDevPathSize + + sizeof (BBS_TABLE) + + sizeof (UINT16); + + Buffer = AllocateZeroPool (BufferSize); + if (Buffer == NULL) { + FreePool (NewBbsDevPathNode); + FreePool (CurrentBbsDevPath); + return EFI_OUT_OF_RESOURCES; + } + + Ptr = (UINT8 *) Buffer; + + *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE; + Ptr += sizeof (UINT32); + + *((UINT16 *) Ptr) = CurrentBbsDevPathSize; + Ptr += sizeof (UINT16); + + CopyMem ( + Ptr, + BootDesc, + StrSize (BootDesc) + ); + Ptr += StrSize (BootDesc); + + CopyMem ( + Ptr, + CurrentBbsDevPath, + CurrentBbsDevPathSize + ); + Ptr += CurrentBbsDevPathSize; + + CopyMem ( + Ptr, + CurrentBbsEntry, + sizeof (BBS_TABLE) + ); + + Ptr += sizeof (BBS_TABLE); + *((UINT16 *) Ptr) = (UINT16) Index; + + Status = gRT->SetVariable ( + BootString, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BufferSize, + Buffer + ); + + FreePool (Buffer); + + Buffer = NULL; + + NewBootOrderList = AllocateZeroPool (*BootOrderListSize + sizeof (UINT16)); + if (NULL == NewBootOrderList) { + FreePool (NewBbsDevPathNode); + FreePool (CurrentBbsDevPath); + return EFI_OUT_OF_RESOURCES; + } + + if (*BootOrderList != NULL) { + CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize); + FreePool (*BootOrderList); + } + + BootOrderLastIndex = (UINTN) (*BootOrderListSize / sizeof (UINT16)); + NewBootOrderList[BootOrderLastIndex] = CurrentBootOptionNo; + *BootOrderListSize += sizeof (UINT16); + *BootOrderList = NewBootOrderList; + + FreePool (NewBbsDevPathNode); + FreePool (CurrentBbsDevPath); + return Status; +} + +/** + Check if the boot option is a legacy one. + + @param BootOptionVar The boot option data payload. + @param BbsEntry The BBS Table. + @param BbsIndex The table index. + + @retval TRUE It is a legacy boot option. + @retval FALSE It is not a legacy boot option. + +**/ +BOOLEAN +BdsIsLegacyBootOption ( + IN UINT8 *BootOptionVar, + OUT BBS_TABLE **BbsEntry, + OUT UINT16 *BbsIndex + ) +{ + UINT8 *Ptr; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BOOLEAN Ret; + UINT16 DevPathLen; + + Ptr = BootOptionVar; + Ptr += sizeof (UINT32); + DevPathLen = *(UINT16 *) Ptr; + Ptr += sizeof (UINT16); + Ptr += StrSize ((UINT16 *) Ptr); + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) { + Ptr += DevPathLen; + *BbsEntry = (BBS_TABLE *) Ptr; + Ptr += sizeof (BBS_TABLE); + *BbsIndex = *(UINT16 *) Ptr; + Ret = TRUE; + } else { + *BbsEntry = NULL; + Ret = FALSE; + } + + return Ret; +} + +/** + Delete all the invalid legacy boot options. + + @retval EFI_SUCCESS All invalide legacy boot options are deleted. + @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory. + @retval EFI_NOT_FOUND Fail to retrive variable of boot order. +**/ +EFI_STATUS +EFIAPI +BdsDeleteAllInvalidLegacyBootOptions ( + VOID + ) +{ + UINT16 *BootOrder; + UINT8 *BootOptionVar; + UINTN BootOrderSize; + UINTN BootOptionSize; + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + BBS_TABLE *BbsEntry; + UINT16 BbsIndex; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Index; + UINT16 BootOption[10]; + UINT16 BootDesc[100]; + BOOLEAN DescStringMatch; + + Status = EFI_SUCCESS; + BootOrder = NULL; + BootOrderSize = 0; + HddCount = 0; + BbsCount = 0; + LocalHddInfo = NULL; + LocalBbsTable = NULL; + BbsEntry = NULL; + + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + if (BootOrder == NULL) { + BootOrderSize = 0; + } + + Index = 0; + while (Index < BootOrderSize / sizeof (UINT16)) { + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]); + BootOptionVar = BdsLibGetVariableAndSize ( + BootOption, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (NULL == BootOptionVar) { + BootOptionSize = 0; + Status = gRT->GetVariable ( + BootOption, + &gEfiGlobalVariableGuid, + NULL, + &BootOptionSize, + BootOptionVar + ); + if (Status == EFI_NOT_FOUND) { + // + // Update BootOrder + // + BdsDeleteBootOption ( + BootOrder[Index], + BootOrder, + &BootOrderSize + ); + continue; + } else { + FreePool (BootOrder); + return EFI_OUT_OF_RESOURCES; + } + } + + // + // Skip Non-Legacy boot option + // + if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) { + if (BootOptionVar!= NULL) { + FreePool (BootOptionVar); + } + Index++; + continue; + } + + if (BbsIndex < BbsCount) { + // + // Check if BBS Description String is changed + // + DescStringMatch = FALSE; + BdsBuildLegacyDevNameString ( + &LocalBbsTable[BbsIndex], + BbsIndex, + sizeof (BootDesc), + BootDesc + ); + + if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) { + DescStringMatch = TRUE; + } + + if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM)) && + (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) && + DescStringMatch) { + Index++; + continue; + } + } + + if (BootOptionVar != NULL) { + FreePool (BootOptionVar); + } + // + // should delete + // + BdsDeleteBootOption ( + BootOrder[Index], + BootOrder, + &BootOrderSize + ); + } + + // + // Adjust the number of boot options. + // + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderSize, + BootOrder + ); + if (BootOrder != NULL) { + FreePool (BootOrder); + } + + return Status; +} + +/** + Find all legacy boot option by device type. + + @param BootOrder The boot order array. + @param BootOptionNum The number of boot option. + @param DevType Device type. + @param DevName Device name. + @param Attribute The boot option attribute. + @param BbsIndex The BBS table index. + @param OptionNumber The boot option index. + + @retval TRUE The Legacy boot option is found. + @retval FALSE The legacy boot option is not found. + +**/ +BOOLEAN +BdsFindLegacyBootOptionByDevTypeAndName ( + IN UINT16 *BootOrder, + IN UINTN BootOptionNum, + IN UINT16 DevType, + IN CHAR16 *DevName, + OUT UINT32 *Attribute, + OUT UINT16 *BbsIndex, + OUT UINT16 *OptionNumber + ) +{ + UINTN Index; + CHAR16 BootOption[9]; + UINTN BootOptionSize; + UINT8 *BootOptionVar; + BBS_TABLE *BbsEntry; + BOOLEAN Found; + + BbsEntry = NULL; + Found = FALSE; + + if (NULL == BootOrder) { + return Found; + } + + // + // Loop all boot option from variable + // + for (Index = 0; Index < BootOptionNum; Index++) { + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", (UINTN) BootOrder[Index]); + BootOptionVar = BdsLibGetVariableAndSize ( + BootOption, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (NULL == BootOptionVar) { + continue; + } + + // + // Skip Non-legacy boot option + // + if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) { + FreePool (BootOptionVar); + continue; + } + + if ( + (BbsEntry->DeviceType != DevType) || + (StrCmp (DevName, (CHAR16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) != 0) + ) { + FreePool (BootOptionVar); + continue; + } + + *Attribute = *(UINT32 *) BootOptionVar; + *OptionNumber = BootOrder[Index]; + Found = TRUE; + FreePool (BootOptionVar); + break; + } + + return Found; +} + +/** + Create a legacy boot option. + + @param BbsItem The BBS Table entry. + @param Index Index of the specified entry in BBS table. + @param BootOrderList The boot order list. + @param BootOrderListSize The size of boot order list. + + @retval EFI_OUT_OF_RESOURCE No enough memory. + @retval EFI_SUCCESS The function complete successfully. + @return Other value if the legacy boot option is not created. + +**/ +EFI_STATUS +BdsCreateOneLegacyBootOption ( + IN BBS_TABLE *BbsItem, + IN UINTN Index, + IN OUT UINT16 **BootOrderList, + IN OUT UINTN *BootOrderListSize + ) +{ + BBS_BBS_DEVICE_PATH BbsDevPathNode; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + + DevPath = NULL; + + // + // Create device path node. + // + BbsDevPathNode.Header.Type = BBS_DEVICE_PATH; + BbsDevPathNode.Header.SubType = BBS_BBS_DP; + SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH)); + BbsDevPathNode.DeviceType = BbsItem->DeviceType; + CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16)); + + DevPath = AppendDevicePathNode ( + NULL, + (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode + ); + if (NULL == DevPath) { + return EFI_OUT_OF_RESOURCES; + } + + Status = BdsCreateLegacyBootOption ( + BbsItem, + DevPath, + Index, + BootOrderList, + BootOrderListSize + ); + BbsItem->BootPriority = 0x00; + + FreePool (DevPath); + + return Status; +} + +/** + Add the legacy boot options from BBS table if they do not exist. + + @retval EFI_SUCCESS The boot options are added successfully + or they are already in boot options. + @retval EFI_NOT_FOUND No legacy boot options is found. + @retval EFI_OUT_OF_RESOURCE No enough memory. + @return Other value LegacyBoot options are not added. +**/ +EFI_STATUS +EFIAPI +BdsAddNonExistingLegacyBootOptions ( + VOID + ) +{ + UINT16 *BootOrder; + UINTN BootOrderSize; + EFI_STATUS Status; + CHAR16 Desc[100]; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + UINT16 BbsIndex; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINT16 Index; + UINT32 Attribute; + UINT16 OptionNumber; + BOOLEAN Exist; + + HddCount = 0; + BbsCount = 0; + LocalHddInfo = NULL; + LocalBbsTable = NULL; + + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + if (BootOrder == NULL) { + BootOrderSize = 0; + } + + for (Index = 0; Index < BbsCount; Index++) { + if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) + ) { + continue; + } + + BdsBuildLegacyDevNameString (&LocalBbsTable[Index], Index, sizeof (Desc), Desc); + + Exist = BdsFindLegacyBootOptionByDevTypeAndName ( + BootOrder, + BootOrderSize / sizeof (UINT16), + LocalBbsTable[Index].DeviceType, + Desc, + &Attribute, + &BbsIndex, + &OptionNumber + ); + if (!Exist) { + // + // Not found such type of legacy device in boot options or we found but it's disabled + // so we have to create one and put it to the tail of boot order list + // + Status = BdsCreateOneLegacyBootOption ( + &LocalBbsTable[Index], + Index, + &BootOrder, + &BootOrderSize + ); + if (EFI_ERROR (Status)) { + break; + } + BbsIndex = Index; + OptionNumber = BootOrder[BootOrderSize / sizeof (UINT16) - 1]; + } + + ASSERT (BbsIndex == Index); + } + + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderSize, + BootOrder + ); + if (BootOrder != NULL) { + FreePool (BootOrder); + } + + return Status; +} + +/** + Fill the device order buffer. + + @param BbsTable The BBS table. + @param BbsType The BBS Type. + @param BbsCount The BBS Count. + @param Buf device order buffer. + + @return The device order buffer. + +**/ +UINT16 * +BdsFillDevOrderBuf ( + IN BBS_TABLE *BbsTable, + IN BBS_TYPE BbsType, + IN UINTN BbsCount, + OUT UINT16 *Buf + ) +{ + UINTN Index; + + for (Index = 0; Index < BbsCount; Index++) { + if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) { + continue; + } + + if (BbsTable[Index].DeviceType != BbsType) { + continue; + } + + *Buf = (UINT16) (Index & 0xFF); + Buf++; + } + + return Buf; +} + +/** + Create the device order buffer. + + @param BbsTable The BBS table. + @param BbsCount The BBS Count. + + @retval EFI_SUCCES The buffer is created and the EFI variable named + VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid is + set correctly. + @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough. + @retval EFI_DEVICE_ERROR Fail to add the device order into EFI variable fail + because of hardware error. +**/ +EFI_STATUS +BdsCreateDevOrder ( + IN BBS_TABLE *BbsTable, + IN UINT16 BbsCount + ) +{ + UINTN Index; + UINTN FDCount; + UINTN HDCount; + UINTN CDCount; + UINTN NETCount; + UINTN BEVCount; + UINTN TotalSize; + UINTN HeaderSize; + LEGACY_DEV_ORDER_ENTRY *DevOrder; + LEGACY_DEV_ORDER_ENTRY *DevOrderPtr; + EFI_STATUS Status; + + FDCount = 0; + HDCount = 0; + CDCount = 0; + NETCount = 0; + BEVCount = 0; + TotalSize = 0; + HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16); + DevOrder = NULL; + Status = EFI_SUCCESS; + + // + // Count all boot devices + // + for (Index = 0; Index < BbsCount; Index++) { + if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) { + continue; + } + + switch (BbsTable[Index].DeviceType) { + case BBS_FLOPPY: + FDCount++; + break; + + case BBS_HARDDISK: + HDCount++; + break; + + case BBS_CDROM: + CDCount++; + break; + + case BBS_EMBED_NETWORK: + NETCount++; + break; + + case BBS_BEV_DEVICE: + BEVCount++; + break; + + default: + break; + } + } + + TotalSize += (HeaderSize + sizeof (UINT16) * FDCount); + TotalSize += (HeaderSize + sizeof (UINT16) * HDCount); + TotalSize += (HeaderSize + sizeof (UINT16) * CDCount); + TotalSize += (HeaderSize + sizeof (UINT16) * NETCount); + TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount); + + // + // Create buffer to hold all boot device order + // + DevOrder = AllocateZeroPool (TotalSize); + if (NULL == DevOrder) { + return EFI_OUT_OF_RESOURCES; + } + DevOrderPtr = DevOrder; + + DevOrderPtr->BbsType = BBS_FLOPPY; + DevOrderPtr->Length = (UINT16) (sizeof (DevOrderPtr->Length) + FDCount * sizeof (UINT16)); + DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, DevOrderPtr->Data); + + DevOrderPtr->BbsType = BBS_HARDDISK; + DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16)); + DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, DevOrderPtr->Data); + + DevOrderPtr->BbsType = BBS_CDROM; + DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16)); + DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, DevOrderPtr->Data); + + DevOrderPtr->BbsType = BBS_EMBED_NETWORK; + DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16)); + DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, DevOrderPtr->Data); + + DevOrderPtr->BbsType = BBS_BEV_DEVICE; + DevOrderPtr->Length = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16)); + DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, DevOrderPtr->Data); + + ASSERT (TotalSize == (UINTN) ((UINT8 *) DevOrderPtr - (UINT8 *) DevOrder)); + + // + // Save device order for legacy boot device to variable. + // + Status = gRT->SetVariable ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + TotalSize, + DevOrder + ); + FreePool (DevOrder); + + return Status; +} + +/** + Add the legacy boot devices from BBS table into + the legacy device boot order. + + @retval EFI_SUCCESS The boot devices are added successfully. + @retval EFI_NOT_FOUND The legacy boot devices are not found. + @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough. + @retval EFI_DEVICE_ERROR Fail to add the legacy device boot order into EFI variable + because of hardware error. +**/ +EFI_STATUS +EFIAPI +BdsUpdateLegacyDevOrder ( + VOID + ) +{ + LEGACY_DEV_ORDER_ENTRY *DevOrder; + LEGACY_DEV_ORDER_ENTRY *NewDevOrder; + LEGACY_DEV_ORDER_ENTRY *Ptr; + LEGACY_DEV_ORDER_ENTRY *NewPtr; + UINTN DevOrderSize; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + UINTN Index; + UINTN Index2; + UINTN *Idx; + UINTN FDCount; + UINTN HDCount; + UINTN CDCount; + UINTN NETCount; + UINTN BEVCount; + UINTN TotalSize; + UINTN HeaderSize; + UINT16 *NewFDPtr; + UINT16 *NewHDPtr; + UINT16 *NewCDPtr; + UINT16 *NewNETPtr; + UINT16 *NewBEVPtr; + UINT16 *NewDevPtr; + UINTN FDIndex; + UINTN HDIndex; + UINTN CDIndex; + UINTN NETIndex; + UINTN BEVIndex; + + Idx = NULL; + FDCount = 0; + HDCount = 0; + CDCount = 0; + NETCount = 0; + BEVCount = 0; + TotalSize = 0; + HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16); + FDIndex = 0; + HDIndex = 0; + CDIndex = 0; + NETIndex = 0; + BEVIndex = 0; + NewDevPtr = NULL; + + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DevOrder = BdsLibGetVariableAndSize ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + &DevOrderSize + ); + if (NULL == DevOrder) { + return BdsCreateDevOrder (LocalBbsTable, BbsCount); + } + // + // First we figure out how many boot devices with same device type respectively + // + for (Index = 0; Index < BbsCount; Index++) { + if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) + ) { + continue; + } + + switch (LocalBbsTable[Index].DeviceType) { + case BBS_FLOPPY: + FDCount++; + break; + + case BBS_HARDDISK: + HDCount++; + break; + + case BBS_CDROM: + CDCount++; + break; + + case BBS_EMBED_NETWORK: + NETCount++; + break; + + case BBS_BEV_DEVICE: + BEVCount++; + break; + + default: + break; + } + } + + TotalSize += (HeaderSize + FDCount * sizeof (UINT16)); + TotalSize += (HeaderSize + HDCount * sizeof (UINT16)); + TotalSize += (HeaderSize + CDCount * sizeof (UINT16)); + TotalSize += (HeaderSize + NETCount * sizeof (UINT16)); + TotalSize += (HeaderSize + BEVCount * sizeof (UINT16)); + + NewDevOrder = AllocateZeroPool (TotalSize); + if (NULL == NewDevOrder) { + return EFI_OUT_OF_RESOURCES; + } + + + + // + // copy FD + // + Ptr = DevOrder; + NewPtr = NewDevOrder; + NewPtr->BbsType = Ptr->BbsType; + NewPtr->Length = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16)); + for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_FLOPPY + ) { + continue; + } + + NewPtr->Data[FDIndex] = Ptr->Data[Index]; + FDIndex++; + } + NewFDPtr = NewPtr->Data; + + // + // copy HD + // + Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]); + NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]); + NewPtr->BbsType = Ptr->BbsType; + NewPtr->Length = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16)); + for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_HARDDISK + ) { + continue; + } + + NewPtr->Data[HDIndex] = Ptr->Data[Index]; + HDIndex++; + } + NewHDPtr = NewPtr->Data; + + // + // copy CD + // + Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]); + NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]); + NewPtr->BbsType = Ptr->BbsType; + NewPtr->Length = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16)); + for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_CDROM + ) { + continue; + } + + NewPtr->Data[CDIndex] = Ptr->Data[Index]; + CDIndex++; + } + NewCDPtr = NewPtr->Data; + + // + // copy NET + // + Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]); + NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]); + NewPtr->BbsType = Ptr->BbsType; + NewPtr->Length = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16)); + for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_EMBED_NETWORK + ) { + continue; + } + + NewPtr->Data[NETIndex] = Ptr->Data[Index]; + NETIndex++; + } + NewNETPtr = NewPtr->Data; + + // + // copy BEV + // + Ptr = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]); + NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]); + NewPtr->BbsType = Ptr->BbsType; + NewPtr->Length = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16)); + for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_BEV_DEVICE + ) { + continue; + } + + NewPtr->Data[BEVIndex] = Ptr->Data[Index]; + BEVIndex++; + } + NewBEVPtr = NewPtr->Data; + + for (Index = 0; Index < BbsCount; Index++) { + if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) + ) { + continue; + } + + switch (LocalBbsTable[Index].DeviceType) { + case BBS_FLOPPY: + Idx = &FDIndex; + NewDevPtr = NewFDPtr; + break; + + case BBS_HARDDISK: + Idx = &HDIndex; + NewDevPtr = NewHDPtr; + break; + + case BBS_CDROM: + Idx = &CDIndex; + NewDevPtr = NewCDPtr; + break; + + case BBS_EMBED_NETWORK: + Idx = &NETIndex; + NewDevPtr = NewNETPtr; + break; + + case BBS_BEV_DEVICE: + Idx = &BEVIndex; + NewDevPtr = NewBEVPtr; + break; + + default: + Idx = NULL; + break; + } + // + // at this point we have copied those valid indexes to new buffer + // and we should check if there is any new appeared boot device + // + if (Idx != NULL) { + for (Index2 = 0; Index2 < *Idx; Index2++) { + if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) { + break; + } + } + + if (Index2 == *Idx) { + // + // Index2 == *Idx means we didn't find Index + // so Index is a new appeared device's index in BBS table + // insert it before disabled indexes. + // + for (Index2 = 0; Index2 < *Idx; Index2++) { + if ((NewDevPtr[Index2] & 0xFF00) == 0xFF00) { + break; + } + } + CopyMem (&NewDevPtr[Index2 + 1], &NewDevPtr[Index2], (*Idx - Index2) * sizeof (UINT16)); + NewDevPtr[Index2] = (UINT16) (Index & 0xFF); + (*Idx)++; + } + } + } + + FreePool (DevOrder); + + Status = gRT->SetVariable ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + TotalSize, + NewDevOrder + ); + FreePool (NewDevOrder); + + return Status; +} + +/** + Set Boot Priority for specified device type. + + @param DeviceType The device type. + @param BbsIndex The BBS index to set the highest priority. Ignore when -1. + @param LocalBbsTable The BBS table. + @param Priority The prority table. + + @retval EFI_SUCCESS The function completes successfully. + @retval EFI_NOT_FOUND Failed to find device. + @retval EFI_OUT_OF_RESOURCES Failed to get the efi variable of device order. + +**/ +EFI_STATUS +BdsSetBootPriority4SameTypeDev ( + IN UINT16 DeviceType, + IN UINTN BbsIndex, + IN OUT BBS_TABLE *LocalBbsTable, + IN OUT UINT16 *Priority + ) +{ + LEGACY_DEV_ORDER_ENTRY *DevOrder; + LEGACY_DEV_ORDER_ENTRY *DevOrderPtr; + UINTN DevOrderSize; + UINTN Index; + + DevOrder = BdsLibGetVariableAndSize ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + &DevOrderSize + ); + if (NULL == DevOrder) { + return EFI_OUT_OF_RESOURCES; + } + + DevOrderPtr = DevOrder; + while ((UINT8 *) DevOrderPtr < (UINT8 *) DevOrder + DevOrderSize) { + if (DevOrderPtr->BbsType == DeviceType) { + break; + } + + DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) ((UINT8 *) DevOrderPtr + sizeof (BBS_TYPE) + DevOrderPtr->Length); + } + + if ((UINT8 *) DevOrderPtr >= (UINT8 *) DevOrder + DevOrderSize) { + FreePool (DevOrder); + return EFI_NOT_FOUND; + } + + if (BbsIndex != (UINTN) -1) { + LocalBbsTable[BbsIndex].BootPriority = *Priority; + (*Priority)++; + } + // + // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled. + // + for (Index = 0; Index < DevOrderPtr->Length / sizeof (UINT16) - 1; Index++) { + if ((DevOrderPtr->Data[Index] & 0xFF00) == 0xFF00) { + // + // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY; + // + } else if (DevOrderPtr->Data[Index] != BbsIndex) { + LocalBbsTable[DevOrderPtr->Data[Index]].BootPriority = *Priority; + (*Priority)++; + } + } + + FreePool (DevOrder); + return EFI_SUCCESS; +} + +/** + Print the BBS Table. + + @param LocalBbsTable The BBS table. + @param BbsCount The count of entry in BBS table. +**/ +VOID +PrintBbsTable ( + IN BBS_TABLE *LocalBbsTable, + IN UINT16 BbsCount + ) +{ + UINT16 Idx; + + DEBUG ((DEBUG_ERROR, "\n")); + DEBUG ((DEBUG_ERROR, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n")); + DEBUG ((DEBUG_ERROR, "=============================================\n")); + for (Idx = 0; Idx < BbsCount; Idx++) { + if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) || + (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY) + ) { + continue; + } + + DEBUG ( + (DEBUG_ERROR, + " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n", + (UINTN) Idx, + (UINTN) LocalBbsTable[Idx].BootPriority, + (UINTN) LocalBbsTable[Idx].Bus, + (UINTN) LocalBbsTable[Idx].Device, + (UINTN) LocalBbsTable[Idx].Function, + (UINTN) LocalBbsTable[Idx].Class, + (UINTN) LocalBbsTable[Idx].SubClass, + (UINTN) LocalBbsTable[Idx].DeviceType, + (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags, + (UINTN) LocalBbsTable[Idx].BootHandlerSegment, + (UINTN) LocalBbsTable[Idx].BootHandlerOffset, + (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset), + (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset)) + ); + } + + DEBUG ((DEBUG_ERROR, "\n")); +} + +/** + Set the boot priority for BBS entries based on boot option entry and boot order. + + @param Entry The boot option is to be checked for refresh BBS table. + + @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully. + @retval EFI_NOT_FOUND BBS entries can't be found. + @retval EFI_OUT_OF_RESOURCES Failed to get the legacy device boot order. +**/ +EFI_STATUS +EFIAPI +BdsRefreshBbsTableForBoot ( + IN BDS_COMMON_OPTION *Entry + ) +{ + EFI_STATUS Status; + UINT16 BbsIndex; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + UINT16 DevType; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Index; + UINT16 Priority; + UINT16 *BootOrder; + UINTN BootOrderSize; + UINT8 *BootOptionVar; + UINTN BootOptionSize; + CHAR16 BootOption[9]; + UINT8 *Ptr; + UINT16 DevPathLen; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + UINT16 *DeviceType; + UINTN DeviceTypeCount; + UINTN DeviceTypeIndex; + + HddCount = 0; + BbsCount = 0; + LocalHddInfo = NULL; + LocalBbsTable = NULL; + DevType = BBS_UNKNOWN; + + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + // + // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY + // We will set them according to the settings setup by user + // + for (Index = 0; Index < BbsCount; Index++) { + if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) || + (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) || + (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) { + LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; + } + } + // + // boot priority always starts at 0 + // + Priority = 0; + if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) { + // + // If Entry stands for a legacy boot option, we prioritize the devices with the same type first. + // + DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType; + BbsIndex = *(UINT16 *) ((BBS_TABLE *) Entry->LoadOptions + 1); + Status = BdsSetBootPriority4SameTypeDev ( + DevType, + BbsIndex, + LocalBbsTable, + &Priority + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // we have to set the boot priority for other BBS entries with different device types + // + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + DeviceType = AllocatePool (BootOrderSize + sizeof (UINT16)); + ASSERT (DeviceType != NULL); + + DeviceType[0] = DevType; + DeviceTypeCount = 1; + for (Index = 0; ((BootOrder != NULL) && (Index < BootOrderSize / sizeof (UINT16))); Index++) { + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]); + BootOptionVar = BdsLibGetVariableAndSize ( + BootOption, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (NULL == BootOptionVar) { + continue; + } + + Ptr = BootOptionVar; + + Ptr += sizeof (UINT32); + DevPathLen = *(UINT16 *) Ptr; + Ptr += sizeof (UINT16); + Ptr += StrSize ((UINT16 *) Ptr); + DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) { + FreePool (BootOptionVar); + continue; + } + + Ptr += DevPathLen; + DevType = ((BBS_TABLE *) Ptr)->DeviceType; + for (DeviceTypeIndex = 0; DeviceTypeIndex < DeviceTypeCount; DeviceTypeIndex++) { + if (DeviceType[DeviceTypeIndex] == DevType) { + break; + } + } + if (DeviceTypeIndex < DeviceTypeCount) { + // + // We don't want to process twice for a device type + // + FreePool (BootOptionVar); + continue; + } + + DeviceType[DeviceTypeCount] = DevType; + DeviceTypeCount++; + + Status = BdsSetBootPriority4SameTypeDev ( + DevType, + (UINTN) -1, + LocalBbsTable, + &Priority + ); + FreePool (BootOptionVar); + if (EFI_ERROR (Status)) { + break; + } + } + + if (BootOrder != NULL) { + FreePool (BootOrder); + } + + DEBUG_CODE_BEGIN(); + PrintBbsTable (LocalBbsTable, BbsCount); + DEBUG_CODE_END(); + + return Status; +} + +/** + Boot the legacy system with the boot option + + @param Option The legacy boot option which have BBS device path + + @retval EFI_UNSUPPORTED There is no legacybios protocol, do not support + legacy boot. + @retval EFI_STATUS Return the status of LegacyBios->LegacyBoot (). + +**/ +EFI_STATUS +BdsLibDoLegacyBoot ( + IN BDS_COMMON_OPTION *Option + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_EVENT LegacyBootEvent; + + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + // + // If no LegacyBios protocol we do not support legacy boot + // + return EFI_UNSUPPORTED; + } + // + // Notes: if we separate the int 19, then we don't need to refresh BBS + // + BdsRefreshBbsTableForBoot (Option); + + // + // 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); + ); + + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Legacy Boot: %S\n", Option->Description)); + return LegacyBios->LegacyBoot ( + LegacyBios, + (BBS_BBS_DEVICE_PATH *) Option->DevicePath, + Option->LoadOptionsSize, + Option->LoadOptions + ); +} + +/** + 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 +IsBootOptionValidNVVarialbe ( + IN BDS_COMMON_OPTION *OptionToCheck + ) +{ + LIST_ENTRY TempList; + BDS_COMMON_OPTION *BootOption; + BOOLEAN Valid; + CHAR16 OptionName[20]; + + Valid = FALSE; + + InitializeListHead (&TempList); + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionToCheck->BootCurrent); + + BootOption = BdsLibVariableToOption (&TempList, OptionName); + if (BootOption == NULL) { + return FALSE; + } + + // + // If the Boot Option Number and Device Path matches, OptionToCheck matches a + // valid EFI NV Boot####. + // + if ((OptionToCheck->BootCurrent == BootOption->BootCurrent) && + (CompareMem (OptionToCheck->DevicePath, BootOption->DevicePath, GetDevicePathSize (OptionToCheck->DevicePath)) == 0)) + { + Valid = TRUE; + } + + FreePool (BootOption); + + return Valid; +} + +/** + 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 +BdsMatchUsbClass ( + 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; +} + +/** + 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 +BdsMatchUsbWwid ( + 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; +} + +/** + Find a USB device path which match the specified short-form device path start + with USB Class or USB WWID device path and load the boot file then return the + image handle. 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 ParentDevicePath The device path of the parent. + @param ShortFormDevicePath The USB Class or USB WWID device path to match. + + @return The image Handle if find load file from specified short-form device path + or NULL if not found. + +**/ +EFI_HANDLE * +BdsFindUsbDevice ( + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *ShortFormDevicePath + ) +{ + EFI_STATUS Status; + UINTN UsbIoHandleCount; + EFI_HANDLE *UsbIoHandleBuffer; + EFI_DEVICE_PATH_PROTOCOL *UsbIoDevicePath; + EFI_USB_IO_PROTOCOL *UsbIo; + UINTN Index; + UINTN ParentSize; + UINTN Size; + EFI_HANDLE ImageHandle; + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *FullDevicePath; + EFI_DEVICE_PATH_PROTOCOL *NextDevicePath; + + FullDevicePath = NULL; + ImageHandle = NULL; + + // + // Get all UsbIo Handles. + // + UsbIoHandleCount = 0; + UsbIoHandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiUsbIoProtocolGuid, + NULL, + &UsbIoHandleCount, + &UsbIoHandleBuffer + ); + if (EFI_ERROR (Status) || (UsbIoHandleCount == 0) || (UsbIoHandleBuffer == NULL)) { + return NULL; + } + + ParentSize = (ParentDevicePath == NULL) ? 0 : GetDevicePathSize (ParentDevicePath); + for (Index = 0; Index < UsbIoHandleCount; Index++) { + // + // Get the Usb IO interface. + // + Status = gBS->HandleProtocol( + UsbIoHandleBuffer[Index], + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo + ); + if (EFI_ERROR (Status)) { + continue; + } + + UsbIoDevicePath = DevicePathFromHandle (UsbIoHandleBuffer[Index]); + if (UsbIoDevicePath == NULL) { + continue; + } + + if (ParentDevicePath != NULL) { + // + // Compare starting part of UsbIoHandle's device path with ParentDevicePath. + // + Size = GetDevicePathSize (UsbIoDevicePath); + if ((Size < ParentSize) || + (CompareMem (UsbIoDevicePath, ParentDevicePath, ParentSize - END_DEVICE_PATH_LENGTH) != 0)) { + continue; + } + } + + if (BdsMatchUsbClass (UsbIo, (USB_CLASS_DEVICE_PATH *) ShortFormDevicePath) || + BdsMatchUsbWwid (UsbIo, (USB_WWID_DEVICE_PATH *) ShortFormDevicePath)) { + // + // Try to find if there is the boot file in this DevicePath + // + NextDevicePath = NextDevicePathNode (ShortFormDevicePath); + if (!IsDevicePathEnd (NextDevicePath)) { + FullDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePath); + // + // Connect the full device path, so that Simple File System protocol + // could be installed for this USB device. + // + BdsLibConnectDevicePath (FullDevicePath); + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad)); + Status = gBS->LoadImage ( + TRUE, + gImageHandle, + FullDevicePath, + NULL, + 0, + &ImageHandle + ); + FreePool (FullDevicePath); + } else { + FullDevicePath = UsbIoDevicePath; + Status = EFI_NOT_FOUND; + } + + // + // 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 for removable device. + // + if (EFI_ERROR (Status)) { + // + // check if there is a bootable removable media could be found in this device path , + // and get the bootable media handle + // + Handle = BdsLibGetBootableHandle(UsbIoDevicePath); + if (Handle == NULL) { + continue; + } + // + // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media + // machinename is ia32, ia64, x64, ... + // + FullDevicePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME); + if (FullDevicePath != NULL) { + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad)); + Status = gBS->LoadImage ( + TRUE, + gImageHandle, + FullDevicePath, + NULL, + 0, + &ImageHandle + ); + if (EFI_ERROR (Status)) { + // + // The DevicePath failed, and it's not a valid + // removable media device. + // + continue; + } + } else { + continue; + } + } + break; + } + } + + FreePool (UsbIoHandleBuffer); + return ImageHandle; +} + +/** + Expand USB Class or USB WWID device path node to be full device path of a USB + device in platform then load the boot file on this full device path and return the + image handle. + + 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 The Boot Option device path. + + @return The image handle of boot file, or NULL if there is no boot file found in + the specified USB Class or USB WWID device path. + +**/ +EFI_HANDLE * +BdsExpandUsbShortFormDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_HANDLE *ImageHandle; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *ShortFormDevicePath; + + // + // Search for USB Class or USB WWID device path node. + // + ShortFormDevicePath = NULL; + ImageHandle = NULL; + TempDevicePath = DevicePath; + while (!IsDevicePathEnd (TempDevicePath)) { + if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) && + ((DevicePathSubType (TempDevicePath) == MSG_USB_CLASS_DP) || + (DevicePathSubType (TempDevicePath) == MSG_USB_WWID_DP))) { + ShortFormDevicePath = TempDevicePath; + break; + } + TempDevicePath = NextDevicePathNode (TempDevicePath); + } + + if (ShortFormDevicePath == NULL) { + // + // No USB Class or USB WWID device path node found, do nothing. + // + return NULL; + } + + if (ShortFormDevicePath == DevicePath) { + // + // Boot Option device path starts with USB Class or USB WWID device path. + // + ImageHandle = BdsFindUsbDevice (NULL, ShortFormDevicePath); + if (ImageHandle == NULL) { + // + // Failed to find a match in existing devices, connect the short form USB + // device path and try again. + // + BdsLibConnectUsbDevByShortFormDP (0xff, ShortFormDevicePath); + ImageHandle = BdsFindUsbDevice (NULL, ShortFormDevicePath); + } + } else { + // + // Boot Option device path contains USB Class or USB WWID device path node. + // + + // + // Prepare the parent device path for search. + // + TempDevicePath = DuplicateDevicePath (DevicePath); + ASSERT (TempDevicePath != NULL); + SetDevicePathEndNode (((UINT8 *) TempDevicePath) + ((UINTN) ShortFormDevicePath - (UINTN) DevicePath)); + + // + // The USB Host Controller device path is already in Boot Option device path + // and USB Bus driver already support RemainingDevicePath starts with USB + // Class or USB WWID device path, so just search in existing USB devices and + // doesn't perform ConnectController here. + // + ImageHandle = BdsFindUsbDevice (TempDevicePath, ShortFormDevicePath); + FreePool (TempDevicePath); + } + + return ImageHandle; +} + +/** + Process the boot option follow the UEFI specification and + special treat the legacy boot option with BBS_DEVICE_PATH. + + @param Option The boot option need to be processed + @param DevicePath The device path which describe where to load the + boot image or the legacy BBS device path to boot + the legacy OS + @param ExitDataSize The size of exit data. + @param ExitData Data returned when Boot image failed. + + @retval EFI_SUCCESS Boot from the input boot option successfully. + @retval EFI_NOT_FOUND If the Device Path is not found in the system + +**/ +EFI_STATUS +EFIAPI +BdsLibBootViaBootOption ( + IN BDS_COMMON_OPTION *Option, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINTN *ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_STATUS StatusLogo; + EFI_HANDLE Handle; + EFI_HANDLE ImageHandle; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; + EFI_DEVICE_PATH_PROTOCOL *WorkingDevicePath; + EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save; + LIST_ENTRY TempBootLists; + EFI_BOOT_LOGO_PROTOCOL *BootLogo; + + *ExitDataSize = 0; + *ExitData = NULL; + + // + // Notes: this code can be remove after the s3 script table + // hook on the event EVT_SIGNAL_READY_TO_BOOT or + // EVT_SIGNAL_LEGACY_BOOT + // + Status = gBS->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid, NULL, (VOID **) &AcpiS3Save); + if (!EFI_ERROR (Status)) { + AcpiS3Save->S3Save (AcpiS3Save, NULL); + } + // + // If it's Device Path that starts with a hard drive path, append it with the front part to compose a + // full device path + // + WorkingDevicePath = NULL; + if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)) { + WorkingDevicePath = BdsExpandPartitionPartialDevicePathToFull ( + (HARDDRIVE_DEVICE_PATH *)DevicePath + ); + if (WorkingDevicePath != NULL) { + DevicePath = WorkingDevicePath; + } + } + + // + // Set Boot Current + // + if (IsBootOptionValidNVVarialbe (Option)) { + // + // For a temporary boot (i.e. a boot by selected a EFI Shell using "Boot From File"), Boot Current is actually not valid. + // In this case, "BootCurrent" is not created. + // Only create the BootCurrent variable when it points to a valid Boot#### variable. + // + gRT->SetVariable ( + L"BootCurrent", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (UINT16), + &Option->BootCurrent + ); + } + + // + // 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)); + + // + // Signal the EVT_SIGNAL_READY_TO_BOOT event + // + EfiSignalEventReadyToBoot(); + + // + // Expand USB Class or USB WWID device path node to be full device path of a USB + // device in platform then load the boot file on this full device path and get the + // image handle. + // + ImageHandle = BdsExpandUsbShortFormDevicePath (DevicePath); + + // + // Adjust the different type memory page number just before booting + // and save the updated info into the variable for next boot to use + // + BdsSetMemoryTypeInformationVariable (); + + // + // By expanding the USB Class or WWID device path, the ImageHandle has returnned. + // Here get the ImageHandle for the non USB class or WWID device path. + // + if (ImageHandle == NULL) { + ASSERT (Option->DevicePath != NULL); + if ((DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) && + (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP) + ) { + // + // Check to see if we should legacy BOOT. If yes then do the legacy boot + // + return BdsLibDoLegacyBoot (Option); + } + + // + // If the boot option point to Internal FV shell, make sure it is valid + // + Status = BdsLibUpdateFvFileDevicePath (&DevicePath, PcdGetPtr(PcdShellFile)); + if (!EFI_ERROR(Status)) { + if (Option->DevicePath != NULL) { + FreePool(Option->DevicePath); + } + Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath)); + ASSERT(Option->DevicePath != NULL); + CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath)); + // + // Update the shell boot option + // + InitializeListHead (&TempBootLists); + BdsLibRegisterNewOption (&TempBootLists, DevicePath, L"EFI Internal Shell", L"BootOrder"); + + // + // free the temporary device path created by BdsLibUpdateFvFileDevicePath() + // + FreePool (DevicePath); + DevicePath = Option->DevicePath; + } + + DEBUG_CODE_BEGIN(); + + if (Option->Description == NULL) { + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting from unknown device path\n")); + } else { + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting %S\n", Option->Description)); + } + + DEBUG_CODE_END(); + + // + // Report status code for OS Loader LoadImage. + // + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad)); + Status = gBS->LoadImage ( + TRUE, + gImageHandle, + DevicePath, + NULL, + 0, + &ImageHandle + ); + + // + // 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 for removable device. + // + if (EFI_ERROR (Status)) { + // + // check if there is a bootable removable media could be found in this device path , + // and get the bootable media handle + // + Handle = BdsLibGetBootableHandle(DevicePath); + if (Handle != NULL) { + // + // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media + // machinename is ia32, ia64, x64, ... + // + FilePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME); + if (FilePath != NULL) { + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad)); + Status = gBS->LoadImage ( + TRUE, + gImageHandle, + FilePath, + NULL, + 0, + &ImageHandle + ); + } + } + } + } + // + // Provide the image with it's load options + // + if ((ImageHandle == NULL) || (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) + ); + goto Done; + } + + Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo); + ASSERT_EFI_ERROR (Status); + + if (Option->LoadOptionsSize != 0) { + ImageInfo->LoadOptionsSize = Option->LoadOptionsSize; + ImageInfo->LoadOptions = Option->LoadOptions; + } + + // + // 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 + // the 5 Minute 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 for OS Loader StartImage. + // + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderStart)); + + Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData); + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", 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) + ); + } + + // + // Clear the Watchdog Timer after the image returns + // + gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL); + +Done: + // + // Set Logo status invalid after trying one boot option + // + BootLogo = NULL; + StatusLogo = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo); + if (!EFI_ERROR (StatusLogo) && (BootLogo != NULL)) { + BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0); + } + + // + // Clear Boot Current + // + gRT->SetVariable ( + L"BootCurrent", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + 0, + &Option->BootCurrent + ); + + return Status; +} + + +/** + 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 HardDriveDevicePath EFI Device Path to boot, if it starts with a hard + drive media device path. + @return A Pointer to the full device path or NULL if a valid Hard Drive devic path + cannot be found. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +BdsExpandPartitionPartialDevicePathToFull ( + IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath + ) +{ + EFI_STATUS Status; + UINTN BlockIoHandleCount; + EFI_HANDLE *BlockIoBuffer; + EFI_DEVICE_PATH_PROTOCOL *FullDevicePath; + EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + 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 HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable. + // If exist, search the front path which point to partition node in the variable instants. + // If fail to find or HD_BOOT_DEVICE_PATH_VARIABLE_NAME not exist, reconnect all and search in all system + // + CachedDevicePath = BdsLibGetVariableAndSize ( + HD_BOOT_DEVICE_PATH_VARIABLE_NAME, + &gHdBootDevicePathVariablGuid, + &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, HardDriveDevicePath)) { + // + // Connect the device path instance, the device path point to hard drive media device path node + // e.g. ACPI() /PCI()/ATA()/Partition() + // + Status = BdsLibConnectDevicePath (Instance); + 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. + // + DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath); + FullDevicePath = AppendDevicePath (Instance, DevicePath); + + // + // Adjust the HD_BOOT_DEVICE_PATH_VARIABLE_NAME instances sequence if the matched one is not first one. + // + if (NeedAdjust) { + // + // First delete the matched instance. + // + TempNewDevicePath = CachedDevicePath; + CachedDevicePath = BdsLibDelPartMatchInstance (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 ( + HD_BOOT_DEVICE_PATH_VARIABLE_NAME, + &gHdBootDevicePathVariablGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + GetDevicePathSize (CachedDevicePath), + CachedDevicePath + ); + } + + FreePool (Instance); + FreePool (CachedDevicePath); + return FullDevicePath; + } + } + + // + // If we get here we fail to find or HD_BOOT_DEVICE_PATH_VARIABLE_NAME not exist, and now we need + // to search all devices in the system for a matched partition + // + BdsLibConnectAllDriversToAllControllers (); + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer); + if (EFI_ERROR (Status) || BlockIoHandleCount == 0 || BlockIoBuffer == NULL) { + // + // If there was an error or there are no device handles that support + // the BLOCK_IO Protocol, then return. + // + return 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, HardDriveDevicePath)) { + // + // Find the matched partition device path + // + DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath); + FullDevicePath = AppendDevicePath (BlockIoDevicePath, DevicePath); + + // + // Save the matched partition device path in HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable + // + if (CachedDevicePath != NULL) { + // + // Save the matched partition device path as first instance of HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable + // + if (BdsLibMatchDevicePaths (CachedDevicePath, BlockIoDevicePath)) { + TempNewDevicePath = CachedDevicePath; + CachedDevicePath = BdsLibDelPartMatchInstance (CachedDevicePath, BlockIoDevicePath); + FreePool(TempNewDevicePath); + } + + if (CachedDevicePath != NULL) { + TempNewDevicePath = CachedDevicePath; + CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath); + FreePool(TempNewDevicePath); + } else { + CachedDevicePath = DuplicateDevicePath (BlockIoDevicePath); + } + + // + // 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 HD_BOOT_DEVICE_PATH_VARIABLE_NAME 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 ( + HD_BOOT_DEVICE_PATH_VARIABLE_NAME, + &gHdBootDevicePathVariablGuid, + 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); + } + return FullDevicePath; +} + +/** + 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 +EFIAPI +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; +} + +/** + Delete the boot option associated with the handle passed in. + + @param Handle The handle which present the device path to create + boot option + + @retval EFI_SUCCESS Delete the boot option success + @retval EFI_NOT_FOUND If the Device Path is not found in the system + @retval EFI_OUT_OF_RESOURCES Lack of memory resource + @retval Other Error return value from SetVariable() + +**/ +EFI_STATUS +BdsLibDeleteOptionFromHandle ( + IN EFI_HANDLE Handle + ) +{ + UINT16 *BootOrder; + UINT8 *BootOptionVar; + UINTN BootOrderSize; + UINTN BootOptionSize; + EFI_STATUS Status; + UINTN Index; + UINT16 BootOption[BOOT_OPTION_MAX_CHAR]; + UINTN DevicePathSize; + UINTN OptionDevicePathSize; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath; + UINT8 *TempPtr; + + Status = EFI_SUCCESS; + BootOrder = NULL; + BootOrderSize = 0; + + // + // Check "BootOrder" variable, if no, means there is no any boot order. + // + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + if (BootOrder == NULL) { + return EFI_NOT_FOUND; + } + + // + // Convert device handle to device path protocol instance + // + DevicePath = DevicePathFromHandle (Handle); + if (DevicePath == NULL) { + return EFI_NOT_FOUND; + } + DevicePathSize = GetDevicePathSize (DevicePath); + + // + // Loop all boot order variable and find the matching device path + // + Index = 0; + while (Index < BootOrderSize / sizeof (UINT16)) { + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]); + BootOptionVar = BdsLibGetVariableAndSize ( + BootOption, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + + if (BootOptionVar == NULL) { + FreePool (BootOrder); + return EFI_OUT_OF_RESOURCES; + } + + if (!ValidateOption(BootOptionVar, BootOptionSize)) { + BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize); + FreePool (BootOptionVar); + Index++; + continue; + } + + TempPtr = BootOptionVar; + TempPtr += sizeof (UINT32) + sizeof (UINT16); + TempPtr += StrSize ((CHAR16 *) TempPtr); + OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr; + OptionDevicePathSize = GetDevicePathSize (OptionDevicePath); + + // + // Check whether the device path match + // + if ((OptionDevicePathSize == DevicePathSize) && + (CompareMem (DevicePath, OptionDevicePath, DevicePathSize) == 0)) { + BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize); + FreePool (BootOptionVar); + break; + } + + FreePool (BootOptionVar); + Index++; + } + + // + // Adjust number of boot option for "BootOrder" variable. + // + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderSize, + BootOrder + ); + + FreePool (BootOrder); + + return Status; +} + + +/** + Delete all invalid EFI boot options. + + @retval EFI_SUCCESS Delete all invalid boot option success + @retval EFI_NOT_FOUND Variable "BootOrder" is not found + @retval EFI_OUT_OF_RESOURCES Lack of memory resource + @retval Other Error return value from SetVariable() + +**/ +EFI_STATUS +BdsDeleteAllInvalidEfiBootOption ( + VOID + ) +{ + UINT16 *BootOrder; + UINT8 *BootOptionVar; + UINTN BootOrderSize; + UINTN BootOptionSize; + EFI_STATUS Status; + UINTN Index; + UINTN Index2; + UINT16 BootOption[BOOT_OPTION_MAX_CHAR]; + EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath; + UINT8 *TempPtr; + CHAR16 *Description; + BOOLEAN Corrupted; + + Status = EFI_SUCCESS; + BootOrder = NULL; + Description = NULL; + OptionDevicePath = NULL; + BootOrderSize = 0; + Corrupted = FALSE; + + // + // Check "BootOrder" variable firstly, this variable hold the number of boot options + // + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + if (NULL == BootOrder) { + return EFI_NOT_FOUND; + } + + Index = 0; + while (Index < BootOrderSize / sizeof (UINT16)) { + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]); + BootOptionVar = BdsLibGetVariableAndSize ( + BootOption, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (NULL == BootOptionVar) { + FreePool (BootOrder); + return EFI_OUT_OF_RESOURCES; + } + + if (!ValidateOption(BootOptionVar, BootOptionSize)) { + Corrupted = TRUE; + } else { + TempPtr = BootOptionVar; + TempPtr += sizeof (UINT32) + sizeof (UINT16); + Description = (CHAR16 *) TempPtr; + TempPtr += StrSize ((CHAR16 *) TempPtr); + OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr; + + // + // Skip legacy boot option (BBS boot device) + // + if ((DevicePathType (OptionDevicePath) == BBS_DEVICE_PATH) && + (DevicePathSubType (OptionDevicePath) == BBS_BBS_DP)) { + FreePool (BootOptionVar); + Index++; + continue; + } + } + + if (Corrupted || !BdsLibIsValidEFIBootOptDevicePathExt (OptionDevicePath, FALSE, Description)) { + // + // Delete this invalid boot option "Boot####" + // + Status = gRT->SetVariable ( + BootOption, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + NULL + ); + // + // Mark this boot option in boot order as deleted + // + BootOrder[Index] = 0xffff; + Corrupted = FALSE; + } + + FreePool (BootOptionVar); + Index++; + } + + // + // Adjust boot order array + // + Index2 = 0; + for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { + if (BootOrder[Index] != 0xffff) { + BootOrder[Index2] = BootOrder[Index]; + Index2 ++; + } + } + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + Index2 * sizeof (UINT16), + BootOrder + ); + + FreePool (BootOrder); + + return Status; +} + + +/** + For EFI boot option, BDS separate them as six types: + 1. Network - The boot option points to the SimpleNetworkProtocol device. + Bds will try to automatically create this type boot option when enumerate. + 2. Shell - The boot option points to internal flash shell. + Bds will try to automatically create this type boot option when enumerate. + 3. Removable BlockIo - The boot option only points to the removable media + device, like USB flash disk, DVD, Floppy etc. + These device should contain a *removable* blockIo + protocol in their device handle. + Bds will try to automatically create this type boot option + when enumerate. + 4. Fixed BlockIo - The boot option only points to a Fixed blockIo device, + like HardDisk. + These device should contain a *fixed* blockIo + protocol in their device handle. + BDS will skip fixed blockIo devices, and NOT + automatically create boot option for them. But BDS + will help to delete those fixed blockIo boot option, + whose description rule conflict with other auto-created + boot options. + 5. Non-BlockIo Simplefile - The boot option points to a device whose handle + has SimpleFileSystem Protocol, but has no blockio + protocol. These devices do not offer blockIo + protocol, but BDS still can get the + \EFI\BOOT\boot{machinename}.EFI by SimpleFileSystem + Protocol. + 6. File - The boot option points to a file. These boot options are usually + created by user manually or OS loader. BDS will not delete or modify + these boot options. + + This function will enumerate all possible boot device in the system, and + automatically create boot options for Network, Shell, Removable BlockIo, + and Non-BlockIo Simplefile devices. + It will only execute once of every boot. + + @param BdsBootOptionList The header of the link list which indexed all + current boot options + + @retval EFI_SUCCESS Finished all the boot device enumerate and create + the boot option base on that boot device + + @retval EFI_OUT_OF_RESOURCES Failed to enumerate the boot device and create the boot option list +**/ +EFI_STATUS +EFIAPI +BdsLibEnumerateAllBootOption ( + IN OUT LIST_ENTRY *BdsBootOptionList + ) +{ + EFI_STATUS Status; + UINT16 FloppyNumber; + UINT16 HarddriveNumber; + UINT16 CdromNumber; + UINT16 UsbNumber; + UINT16 MiscNumber; + UINT16 ScsiNumber; + UINT16 NonBlockNumber; + UINTN NumberBlockIoHandles; + EFI_HANDLE *BlockIoHandles; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + BOOLEAN Removable[2]; + UINTN RemovableIndex; + UINTN Index; + UINTN NumOfLoadFileHandles; + EFI_HANDLE *LoadFileHandles; + UINTN FvHandleCount; + EFI_HANDLE *FvHandleBuffer; + EFI_FV_FILETYPE Type; + UINTN Size; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 AuthenticationStatus; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN DevicePathType; + CHAR16 Buffer[40]; + EFI_HANDLE *FileSystemHandles; + UINTN NumberFileSystemHandles; + BOOLEAN NeedDelete; + EFI_IMAGE_DOS_HEADER DosHeader; + CHAR8 *PlatLang; + CHAR8 *LastLang; + EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + + FloppyNumber = 0; + HarddriveNumber = 0; + CdromNumber = 0; + UsbNumber = 0; + MiscNumber = 0; + ScsiNumber = 0; + PlatLang = NULL; + LastLang = NULL; + ZeroMem (Buffer, sizeof (Buffer)); + + // + // If the boot device enumerate happened, just get the boot + // device from the boot order variable + // + if (mEnumBootDevice) { + GetVariable2 (LAST_ENUM_LANGUAGE_VARIABLE_NAME, &gLastEnumLangGuid, (VOID**)&LastLang, NULL); + GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatLang, NULL); + ASSERT (PlatLang != NULL); + if ((LastLang != NULL) && (AsciiStrCmp (LastLang, PlatLang) == 0)) { + Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder"); + FreePool (LastLang); + FreePool (PlatLang); + return Status; + } else { + Status = gRT->SetVariable ( + LAST_ENUM_LANGUAGE_VARIABLE_NAME, + &gLastEnumLangGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + AsciiStrSize (PlatLang), + PlatLang + ); + ASSERT_EFI_ERROR (Status); + + if (LastLang != NULL) { + FreePool (LastLang); + } + FreePool (PlatLang); + } + } + + // + // Notes: this dirty code is to get the legacy boot option from the + // BBS table and create to variable as the EFI boot option, it should + // be removed after the CSM can provide legacy boot option directly + // + REFRESH_LEGACY_BOOT_OPTIONS; + + // + // Delete invalid boot option + // + BdsDeleteAllInvalidEfiBootOption (); + + // + // Parse removable media followed by fixed media. + // The Removable[] array is used by the for-loop below to create removable media boot options + // at first, and then to create fixed media boot options. + // + Removable[0] = FALSE; + Removable[1] = TRUE; + + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &NumberBlockIoHandles, + &BlockIoHandles + ); + + for (RemovableIndex = 0; RemovableIndex < 2; RemovableIndex++) { + for (Index = 0; Index < NumberBlockIoHandles; Index++) { + Status = gBS->HandleProtocol ( + BlockIoHandles[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + // + // skip the fixed block io then the removable block io + // + if (EFI_ERROR (Status) || (BlkIo->Media->RemovableMedia == Removable[RemovableIndex])) { + continue; + } + DevicePath = DevicePathFromHandle (BlockIoHandles[Index]); + DevicePathType = BdsGetBootTypeFromDevicePath (DevicePath); + + switch (DevicePathType) { + case BDS_EFI_ACPI_FLOPPY_BOOT: + if (FloppyNumber != 0) { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)), FloppyNumber); + } else { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY))); + } + BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer); + FloppyNumber++; + break; + + // + // Assume a removable SATA device should be the DVD/CD device, a fixed SATA device should be the Hard Drive device. + // + case BDS_EFI_MESSAGE_ATAPI_BOOT: + case BDS_EFI_MESSAGE_SATA_BOOT: + if (BlkIo->Media->RemovableMedia) { + if (CdromNumber != 0) { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)), CdromNumber); + } else { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD))); + } + CdromNumber++; + } else { + if (HarddriveNumber != 0) { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_HARDDRIVE)), HarddriveNumber); + } else { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_HARDDRIVE))); + } + HarddriveNumber++; + } + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Buffer: %S\n", Buffer)); + BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer); + break; + + case BDS_EFI_MESSAGE_USB_DEVICE_BOOT: + if (UsbNumber != 0) { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)), UsbNumber); + } else { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB))); + } + BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer); + UsbNumber++; + break; + + case BDS_EFI_MESSAGE_SCSI_BOOT: + if (ScsiNumber != 0) { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)), ScsiNumber); + } else { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI))); + } + BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer); + ScsiNumber++; + break; + + case BDS_EFI_MESSAGE_MISC_BOOT: + if (MiscNumber != 0) { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)), MiscNumber); + } else { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC))); + } + BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer); + MiscNumber++; + break; + + default: + break; + } + } + } + + if (NumberBlockIoHandles != 0) { + FreePool (BlockIoHandles); + } + + // + // If there is simple file protocol which does not consume block Io protocol, create a boot option for it here. + // + NonBlockNumber = 0; + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NumberFileSystemHandles, + &FileSystemHandles + ); + for (Index = 0; Index < NumberFileSystemHandles; Index++) { + Status = gBS->HandleProtocol ( + FileSystemHandles[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + if (!EFI_ERROR (Status)) { + // + // Skip if the file system handle supports a BlkIo protocol, + // + continue; + } + + // + // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI + // machinename is ia32, ia64, x64, ... + // + Hdr.Union = &HdrData; + NeedDelete = TRUE; + Status = BdsLibGetImageHeader ( + FileSystemHandles[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) { + NeedDelete = FALSE; + } + + if (NeedDelete) { + // + // No such file or the file is not a EFI application, delete this boot option + // + BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]); + } else { + if (NonBlockNumber != 0) { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)), NonBlockNumber); + } else { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK))); + } + BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList, Buffer); + NonBlockNumber++; + } + } + + if (NumberFileSystemHandles != 0) { + FreePool (FileSystemHandles); + } + + // + // Parse Network Boot Device + // + NumOfLoadFileHandles = 0; + // + // Search Load File protocol for PXE boot option. + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiLoadFileProtocolGuid, + NULL, + &NumOfLoadFileHandles, + &LoadFileHandles + ); + + for (Index = 0; Index < NumOfLoadFileHandles; Index++) { + if (Index != 0) { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s%d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)), 6); + } else { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s%d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)), 4); + } + BdsLibBuildOptionFromHandle (LoadFileHandles[Index], BdsBootOptionList, Buffer); + } + + if (NumOfLoadFileHandles != 0) { + FreePool (LoadFileHandles); + } + + // + // Check if we have on flash shell + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &FvHandleCount, + &FvHandleBuffer + ); + for (Index = 0; Index < FvHandleCount; Index++) { + gBS->HandleProtocol ( + FvHandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + + Status = Fv->ReadFile ( + Fv, + PcdGetPtr(PcdShellFile), + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + // + // Skip if no shell file in the FV + // + continue; + } + // + // Build the shell boot option + // + BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList); + } + + if (FvHandleCount != 0) { + FreePool (FvHandleBuffer); + } + // + // Make sure every boot only have one time + // boot device enumerate + // + Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder"); + mEnumBootDevice = TRUE; + + return Status; +} + +/** + Build the boot option with the handle parsed in + + @param Handle The handle which present the device path to create + boot option + @param BdsBootOptionList The header of the link list which indexed all + current boot options + @param String The description of the boot option. + +**/ +VOID +EFIAPI +BdsLibBuildOptionFromHandle ( + IN EFI_HANDLE Handle, + IN LIST_ENTRY *BdsBootOptionList, + IN CHAR16 *String + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath = DevicePathFromHandle (Handle); + + // + // Create and register new boot option + // + BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, String, L"BootOrder"); +} + + +/** + Build the on flash shell boot option with the handle parsed in. + + @param Handle The handle which present the device path to create + on flash shell boot option + @param BdsBootOptionList The header of the link list which indexed all + current boot options + +**/ +VOID +EFIAPI +BdsLibBuildOptionFromShell ( + IN EFI_HANDLE Handle, + IN OUT LIST_ENTRY *BdsBootOptionList + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode; + + DevicePath = DevicePathFromHandle (Handle); + + // + // Build the shell device path + // + EfiInitializeFwVolDevicepathNode (&ShellNode, PcdGetPtr(PcdShellFile)); + + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode); + + // + // Create and register the shell boot option + // + BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, L"EFI Internal Shell", L"BootOrder"); + +} + +/** + Boot from the UEFI spec defined "BootNext" variable. + +**/ +VOID +EFIAPI +BdsLibBootNext ( + VOID + ) +{ + UINT16 *BootNext; + UINTN BootNextSize; + CHAR16 Buffer[20]; + BDS_COMMON_OPTION *BootOption; + LIST_ENTRY TempList; + UINTN ExitDataSize; + CHAR16 *ExitData; + + // + // Init the boot option name buffer and temp link list + // + InitializeListHead (&TempList); + ZeroMem (Buffer, sizeof (Buffer)); + + BootNext = BdsLibGetVariableAndSize ( + L"BootNext", + &gEfiGlobalVariableGuid, + &BootNextSize + ); + + // + // Clear the boot next variable first + // + if (BootNext != NULL) { + gRT->SetVariable ( + L"BootNext", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + BootNext + ); + + // + // Start to build the boot option and try to boot + // + UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *BootNext); + BootOption = BdsLibVariableToOption (&TempList, Buffer); + ASSERT (BootOption != NULL); + BdsLibConnectDevicePath (BootOption->DevicePath); + BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData); + } + +} + +/** + Return the bootable media handle. + First, check the device is connected + Second, check whether the device path point to a device which support SimpleFileSystemProtocol, + Third, detect the the default boot file in the Media, and return the removable Media handle. + + @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 +EFIAPI +BdsLibGetBootableHandle ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + EFI_DEVICE_PATH_PROTOCOL *UpdatedDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DupDevicePath; + 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; + + UpdatedDevicePath = DevicePath; + + // + // Enter to critical section to protect the acquired BlockIo instance + // from getting released due to the USB mass storage hotplug event + // + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + // + // 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); + ASSERT_EFI_ERROR (Status); + + // + // 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 + // + + // + // If fail to get bootable handle specified by a USB boot option, the BDS should try to find other bootable device in the same USB bus + // Try to locate the USB node device path first, if fail then use its previous PCI node to search + // + DupDevicePath = DuplicateDevicePath (DevicePath); + ASSERT (DupDevicePath != NULL); + + UpdatedDevicePath = DupDevicePath; + Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle); + // + // if the resulting device path point to a usb node, and the usb node is a dummy node, should only let device path only point to the previous Pci node + // Acpi()/Pci()/Usb() --> Acpi()/Pci() + // + if ((DevicePathType (UpdatedDevicePath) == MESSAGING_DEVICE_PATH) && + (DevicePathSubType (UpdatedDevicePath) == MSG_USB_DP)) { + // + // Remove the usb node, let the device path only point to PCI node + // + SetDevicePathEndNode (UpdatedDevicePath); + UpdatedDevicePath = DupDevicePath; + } else { + UpdatedDevicePath = DevicePath; + } + + // + // Get the device path size of boot option + // + Size = GetDevicePathSize(UpdatedDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node + ReturnHandle = NULL; + 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)- sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node + // + // Check whether the device path of boot option is part of the SimpleFileSystem handle's device path + // + if (Size <= TempSize && CompareMem (TempDevicePath, UpdatedDevicePath, Size)==0) { + // + // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media + // machinename is ia32, ia64, x64, ... + // + Hdr.Union = &HdrData; + Status = BdsLibGetImageHeader ( + 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; + } + } + } + + FreePool(DupDevicePath); + + if (SimpleFileSystemHandles != NULL) { + FreePool(SimpleFileSystemHandles); + } + + gBS->RestoreTPL (OldTpl); + + return ReturnHandle; +} + +/** + Check to see if the network cable is plugged in. If the DevicePath is not + connected it will be connected. + + @param DevicePath Device Path to check + + @retval TRUE DevicePath points to an Network that is connected + @retval FALSE DevicePath does not point to a bootable network + +**/ +BOOLEAN +BdsLibNetworkBootWithMediaPresent ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *UpdatedDevicePath; + EFI_HANDLE Handle; + EFI_SIMPLE_NETWORK_PROTOCOL *Snp; + BOOLEAN MediaPresent; + UINT32 InterruptStatus; + + MediaPresent = FALSE; + + UpdatedDevicePath = DevicePath; + // + // Locate Load File Protocol for PXE boot option first + // + Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &UpdatedDevicePath, &Handle); + if (EFI_ERROR (Status)) { + // + // Device not present so see if we need to connect it + // + Status = BdsLibConnectDevicePath (DevicePath); + if (!EFI_ERROR (Status)) { + // + // This one should work after we did the connect + // + Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &UpdatedDevicePath, &Handle); + } + } + + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp); + if (EFI_ERROR (Status)) { + // + // Failed to open SNP from this handle, try to get SNP from parent handle + // + UpdatedDevicePath = DevicePathFromHandle (Handle); + if (UpdatedDevicePath != NULL) { + Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle); + if (!EFI_ERROR (Status)) { + // + // SNP handle found, get SNP from it + // + Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **) &Snp); + } + } + } + + if (!EFI_ERROR (Status)) { + if (Snp->Mode->MediaPresentSupported) { + if (Snp->Mode->State == EfiSimpleNetworkInitialized) { + // + // Invoke Snp->GetStatus() to refresh the media status + // + Snp->GetStatus (Snp, &InterruptStatus, NULL); + + // + // In case some one else is using the SNP check to see if it's connected + // + MediaPresent = Snp->Mode->MediaPresent; + } else { + // + // No one is using SNP so we need to Start and Initialize so + // MediaPresent will be valid. + // + Status = Snp->Start (Snp); + if (!EFI_ERROR (Status)) { + Status = Snp->Initialize (Snp, 0, 0); + if (!EFI_ERROR (Status)) { + MediaPresent = Snp->Mode->MediaPresent; + Snp->Shutdown (Snp); + } + Snp->Stop (Snp); + } + } + } else { + MediaPresent = TRUE; + } + } + } + + return MediaPresent; +} + +/** + For a bootable Device path, return its boot type. + + @param DevicePath The bootable device Path to check + + @retval BDS_EFI_MEDIA_HD_BOOT If given device path contains MEDIA_DEVICE_PATH type device path node + which subtype is MEDIA_HARDDRIVE_DP + @retval BDS_EFI_MEDIA_CDROM_BOOT If given device path contains MEDIA_DEVICE_PATH type device path node + which subtype is MEDIA_CDROM_DP + @retval BDS_EFI_ACPI_FLOPPY_BOOT If given device path contains ACPI_DEVICE_PATH type device path node + which HID is floppy device. + @retval BDS_EFI_MESSAGE_ATAPI_BOOT 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 BDS_EFI_MESSAGE_SCSI_BOOT 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 BDS_EFI_MESSAGE_USB_DEVICE_BOOT 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 BDS_EFI_MESSAGE_MISC_BOOT If the device path not contains any media device path node, and + its last device path node point to a message device path node. + @retval BDS_LEGACY_BBS_BOOT If given device path contains BBS_DEVICE_PATH type device path node. + @retval BDS_EFI_UNSUPPORT An EFI Removable BlockIO device path not point to a media and message device, + +**/ +UINT32 +EFIAPI +BdsGetBootTypeFromDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ACPI_HID_DEVICE_PATH *Acpi; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode; + UINT32 BootType; + + if (NULL == DevicePath) { + return BDS_EFI_UNSUPPORT; + } + + TempDevicePath = DevicePath; + + while (!IsDevicePathEndType (TempDevicePath)) { + switch (DevicePathType (TempDevicePath)) { + case BBS_DEVICE_PATH: + return BDS_LEGACY_BBS_BOOT; + case MEDIA_DEVICE_PATH: + if (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP) { + return BDS_EFI_MEDIA_HD_BOOT; + } else if (DevicePathSubType (TempDevicePath) == MEDIA_CDROM_DP) { + return BDS_EFI_MEDIA_CDROM_BOOT; + } + break; + case ACPI_DEVICE_PATH: + Acpi = (ACPI_HID_DEVICE_PATH *) TempDevicePath; + if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) { + return BDS_EFI_ACPI_FLOPPY_BOOT; + } + break; + case MESSAGING_DEVICE_PATH: + // + // Get the last device path node + // + LastDeviceNode = NextDevicePathNode (TempDevicePath); + if (DevicePathSubType(LastDeviceNode) == MSG_DEVICE_LOGICAL_UNIT_DP) { + // + // if the next node type is Device Logical Unit, which specify the Logical Unit Number (LUN), + // skip it + // + LastDeviceNode = NextDevicePathNode (LastDeviceNode); + } + // + // if the device path not only point to driver device, it is not a messaging device path, + // + if (!IsDevicePathEndType (LastDeviceNode)) { + break; + } + + switch (DevicePathSubType (TempDevicePath)) { + case MSG_ATAPI_DP: + BootType = BDS_EFI_MESSAGE_ATAPI_BOOT; + break; + + case MSG_USB_DP: + BootType = BDS_EFI_MESSAGE_USB_DEVICE_BOOT; + break; + + case MSG_SCSI_DP: + BootType = BDS_EFI_MESSAGE_SCSI_BOOT; + break; + + case MSG_SATA_DP: + BootType = BDS_EFI_MESSAGE_SATA_BOOT; + break; + + case MSG_MAC_ADDR_DP: + case MSG_VLAN_DP: + case MSG_IPv4_DP: + case MSG_IPv6_DP: + BootType = BDS_EFI_MESSAGE_MAC_BOOT; + break; + + default: + BootType = BDS_EFI_MESSAGE_MISC_BOOT; + break; + } + return BootType; + + default: + break; + } + TempDevicePath = NextDevicePathNode (TempDevicePath); + } + + return BDS_EFI_UNSUPPORT; +} + +/** + Check whether the Device path in a boot option point to a valid bootable device, + And if CheckMedia is true, check the device is ready to boot now. + + @param DevPath the Device path in a boot option + @param CheckMedia if true, check the device is ready to boot now. + + @retval TRUE the Device path is valid + @retval FALSE the Device path is invalid . + +**/ +BOOLEAN +EFIAPI +BdsLibIsValidEFIBootOptDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath, + IN BOOLEAN CheckMedia + ) +{ + return BdsLibIsValidEFIBootOptDevicePathExt (DevPath, CheckMedia, NULL); +} + +/** + Check whether the Device path in a boot option point to a valid bootable device, + And if CheckMedia is true, check the device is ready to boot now. + If Description is not NULL and the device path point to a fixed BlockIo + device, check the description whether conflict with other auto-created + boot options. + + @param DevPath the Device path in a boot option + @param CheckMedia if true, check the device is ready to boot now. + @param Description the description in a boot option + + @retval TRUE the Device path is valid + @retval FALSE the Device path is invalid . + +**/ +BOOLEAN +EFIAPI +BdsLibIsValidEFIBootOptDevicePathExt ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath, + IN BOOLEAN CheckMedia, + IN CHAR16 *Description + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + TempDevicePath = DevPath; + LastDeviceNode = DevPath; + + // + // Check if it's a valid boot option for network boot device. + // Check if there is EfiLoadFileProtocol installed. + // If yes, that means there is a boot option for network. + // + Status = gBS->LocateDevicePath ( + &gEfiLoadFileProtocolGuid, + &TempDevicePath, + &Handle + ); + if (EFI_ERROR (Status)) { + // + // Device not present so see if we need to connect it + // + TempDevicePath = DevPath; + BdsLibConnectDevicePath (TempDevicePath); + Status = gBS->LocateDevicePath ( + &gEfiLoadFileProtocolGuid, + &TempDevicePath, + &Handle + ); + } + + if (!EFI_ERROR (Status)) { + if (!IsDevicePathEnd (TempDevicePath)) { + // + // LoadFile protocol is not installed on handle with exactly the same DevPath + // + return FALSE; + } + + if (CheckMedia) { + // + // Test if it is ready to boot now + // + if (BdsLibNetworkBootWithMediaPresent(DevPath)) { + return TRUE; + } + } else { + return TRUE; + } + } + + // + // If the boot option point to a file, it is a valid EFI boot option, + // and assume it is ready to boot now + // + while (!IsDevicePathEnd (TempDevicePath)) { + // + // If there is USB Class or USB WWID device path node, treat it as valid EFI + // Boot Option. BdsExpandUsbShortFormDevicePath () will be used to expand it + // to full device path. + // + if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) && + ((DevicePathSubType (TempDevicePath) == MSG_USB_CLASS_DP) || + (DevicePathSubType (TempDevicePath) == MSG_USB_WWID_DP))) { + return TRUE; + } + + LastDeviceNode = TempDevicePath; + TempDevicePath = NextDevicePathNode (TempDevicePath); + } + if ((DevicePathType (LastDeviceNode) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (LastDeviceNode) == MEDIA_FILEPATH_DP)) { + return TRUE; + } + + // + // Check if it's a valid boot option for internal FV application + // + if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode) != NULL) { + // + // If the boot option point to internal FV application, make sure it is valid + // + TempDevicePath = DevPath; + Status = BdsLibUpdateFvFileDevicePath ( + &TempDevicePath, + EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode) + ); + if (Status == EFI_ALREADY_STARTED) { + return TRUE; + } else { + if (Status == EFI_SUCCESS) { + FreePool (TempDevicePath); + } + return FALSE; + } + } + + // + // If the boot option point to a blockIO device: + // if it is a removable blockIo device, it is valid. + // if it is a fixed blockIo device, check its description confliction. + // + TempDevicePath = DevPath; + Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle); + if (EFI_ERROR (Status)) { + // + // Device not present so see if we need to connect it + // + Status = BdsLibConnectDevicePath (DevPath); + if (!EFI_ERROR (Status)) { + // + // Try again to get the Block Io protocol after we did the connect + // + TempDevicePath = DevPath; + Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle); + } + } + + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo); + if (!EFI_ERROR (Status)) { + if (CheckMedia) { + // + // Test if it is ready to boot now + // + if (BdsLibGetBootableHandle (DevPath) != NULL) { + return TRUE; + } + } else { + return TRUE; + } + } + } else { + // + // if the boot option point to a simple file protocol which does not consume block Io protocol, it is also a valid EFI boot option, + // + Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &TempDevicePath, &Handle); + if (!EFI_ERROR (Status)) { + if (CheckMedia) { + // + // Test if it is ready to boot now + // + if (BdsLibGetBootableHandle (DevPath) != NULL) { + return TRUE; + } + } else { + return TRUE; + } + } + } + + return FALSE; +} + + +/** + 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 on input, the Fv file device path need to check on + output, the updated valid Fv file device path + @param FileGuid the Fv file guild + + @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid + parameter + @retval EFI_UNSUPPORTED the input DevicePath does not contain Fv file + guild at all + @retval EFI_ALREADY_STARTED the input DevicePath has pointed to Fv file, it is + valid + @retval EFI_SUCCESS has successfully updated the invalid DevicePath, + and return the updated device path in DevicePath + +**/ +EFI_STATUS +EFIAPI +BdsLibUpdateFvFileDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath, + IN EFI_GUID *FileGuid + ) +{ + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode; + EFI_STATUS Status; + EFI_GUID *GuidPoint; + UINTN Index; + UINTN FvHandleCount; + EFI_HANDLE *FvHandleBuffer; + EFI_FV_FILETYPE Type; + UINTN Size; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 AuthenticationStatus; + BOOLEAN FindFvFile; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode; + EFI_HANDLE FoundFvHandle; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + + if ((DevicePath == NULL) || (*DevicePath == NULL)) { + return EFI_INVALID_PARAMETER; + } + if (FileGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check whether the device path point to the default the input Fv file + // + TempDevicePath = *DevicePath; + LastDeviceNode = TempDevicePath; + while (!IsDevicePathEnd (TempDevicePath)) { + LastDeviceNode = TempDevicePath; + TempDevicePath = NextDevicePathNode (TempDevicePath); + } + GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode ( + (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode + ); + if (GuidPoint == NULL) { + // + // if this option does not points to a Fv file, just return EFI_UNSUPPORTED + // + return EFI_UNSUPPORTED; + } + if (!CompareGuid (GuidPoint, FileGuid)) { + // + // If the Fv file is not the input file guid, just return EFI_UNSUPPORTED + // + return EFI_UNSUPPORTED; + } + + // + // Check whether the input Fv file device path is valid + // + TempDevicePath = *DevicePath; + FoundFvHandle = NULL; + Status = gBS->LocateDevicePath ( + &gEfiFirmwareVolume2ProtocolGuid, + &TempDevicePath, + &FoundFvHandle + ); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol ( + FoundFvHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + if (!EFI_ERROR (Status)) { + // + // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there + // + Status = Fv->ReadFile ( + Fv, + FileGuid, + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + return EFI_ALREADY_STARTED; + } + } + } + + // + // Look for the input wanted FV file in current FV + // First, try to look for in Bds own FV. Bds and input wanted FV file usually are in the same FV + // + FindFvFile = FALSE; + FoundFvHandle = NULL; + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol ( + LoadedImage->DeviceHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + if (!EFI_ERROR (Status)) { + Status = Fv->ReadFile ( + Fv, + FileGuid, + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + FindFvFile = TRUE; + FoundFvHandle = LoadedImage->DeviceHandle; + } + } + } + // + // Second, if fail to find, try to enumerate all FV + // + if (!FindFvFile) { + 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)) { + // + // Skip if input Fv file not in the FV + // + continue; + } + FindFvFile = TRUE; + FoundFvHandle = FvHandleBuffer[Index]; + break; + } + + if (FvHandleBuffer != NULL) { + FreePool (FvHandleBuffer); + } + } + + if (FindFvFile) { + // + // Build the shell device path + // + NewDevicePath = DevicePathFromHandle (FoundFvHandle); + EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid); + NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode); + *DevicePath = NewDevicePath; + return EFI_SUCCESS; + } + return EFI_NOT_FOUND; +} diff --git a/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c new file mode 100644 index 0000000000..f487aa611a --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c @@ -0,0 +1,435 @@ +/** @file + BDS Lib functions which relate with connect the device + +Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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 +BdsLibConnectAll ( + VOID + ) +{ + // + // Connect the platform console first + // + BdsLibConnectAllDefaultConsoles (); + + // + // Generic way to connect all the drivers + // + BdsLibConnectAllDriversToAllControllers (); + + // + // Here we have the assumption that we have already had + // platform default console + // + BdsLibConnectAllDefaultConsoles (); +} + + +/** + This function will connect all the system drivers to all controllers + first, and then connect all the console devices the system current + have. After this we should get all the device work and console available + if the system have console device. + +**/ +VOID +BdsLibGenericConnectAll ( + VOID + ) +{ + // + // Most generic way to connect all the drivers + // + BdsLibConnectAllDriversToAllControllers (); + BdsLibConnectAllConsoles (); +} + +/** + 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 + + @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 +BdsLibConnectDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Instance; + EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Next; + EFI_HANDLE Handle; + EFI_HANDLE PreviousHandle; + UINTN Size; + EFI_TPL CurrentTpl; + + if (DevicePathToConnect == NULL) { + return EFI_SUCCESS; + } + + CurrentTpl = EfiGetCurrentTpl (); + + DevicePath = DuplicateDevicePath (DevicePathToConnect); + if (DevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyOfDevicePath = DevicePath; + + do { + // + // The outer loop handles multi instance device paths. + // Only console variables contain multiple instance device paths. + // + // After this call DevicePath points to the next Instance + // + Instance = GetNextDevicePathInstance (&DevicePath, &Size); + if (Instance == NULL) { + FreePool (CopyOfDevicePath); + return EFI_OUT_OF_RESOURCES; + } + + Next = Instance; + while (!IsDevicePathEndType (Next)) { + Next = NextDevicePathNode (Next); + } + + SetDevicePathEndNode (Next); + + // + // 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 = Instance; + 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 (CurrentTpl == TPL_APPLICATION) { + // + // Dispatch calls LoadImage/StartImage which cannot run at TPL > TPL_APPLICATION + // + 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); + } + } + // + // Loop until RemainingDevicePath is an empty device path + // + } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath)); + + } while (DevicePath != NULL); + + if (CopyOfDevicePath != NULL) { + FreePool (CopyOfDevicePath); + } + // + // All handle with DevicePath exists in the handle database + // + return Status; +} + +/** + 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 also will be connected recursively + by gBS->ConnectController(). + + @retval EFI_SUCCESS All handles and it's child handle have been connected + @retval EFI_STATUS Error status returned by of gBS->LocateHandleBuffer(). + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectAllEfi ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; +} + +/** + 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(). + + @retval EFI_SUCCESS All handles have been disconnected + @retval EFI_STATUS Error status returned by of gBS->LocateHandleBuffer(). + +**/ +EFI_STATUS +EFIAPI +BdsLibDisconnectAllEfi ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + + // + // Disconnect all + // + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; +} + + +/** + Connects all drivers to all controllers. + This function make sure all the current system driver will manage + the correspoinding controllers if have. And at the same time, make + sure all the system controllers have driver to manage it if have. + +**/ +VOID +EFIAPI +BdsLibConnectAllDriversToAllControllers ( + VOID + ) +{ + EFI_STATUS Status; + + do { + // + // Connect All EFI 1.10 drivers following EFI 1.10 algorithm + // + BdsLibConnectAllEfi (); + + // + // Check to see if it's possible to dispatch an more DXE drivers. + // The BdsLibConnectAllEfi () may have made new DXE drivers show up. + // If anything 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 HostControllerPI Uhci (0x00) or Ehci (0x20) or Both uhci and ehci + (0xFF) + @param RemainingDevicePath 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 RemainingDevicePath is NULL pointer. + RemainingDevicePath is not a USB device path. + Invalid HostControllerPI type. + @return EFI_SUCCESS Success to connect USB device + @return EFI_NOT_FOUND Fail to find handle for USB controller to connect. + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectUsbDevByShortFormDP( + IN UINT8 HostControllerPI, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleArray; + UINTN HandleArrayCount; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Class[3]; + BOOLEAN AtLeastOneConnected; + + // + // Check the passed in parameters + // + if (RemainingDevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((DevicePathType (RemainingDevicePath) != MESSAGING_DEVICE_PATH) || + ((DevicePathSubType (RemainingDevicePath) != MSG_USB_CLASS_DP) + && (DevicePathSubType (RemainingDevicePath) != MSG_USB_WWID_DP) + )) { + return EFI_INVALID_PARAMETER; + } + + if (HostControllerPI != 0xFF && + HostControllerPI != 0x00 && + HostControllerPI != 0x20) { + 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, + &HandleArrayCount, + &HandleArray + ); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < HandleArrayCount; Index++) { + Status = gBS->HandleProtocol ( + HandleArray[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)) { + if ((PCI_CLASS_SERIAL == Class[2]) && + (PCI_CLASS_SERIAL_USB == Class[1])) { + if (HostControllerPI == Class[0] || HostControllerPI == 0xFF) { + Status = gBS->ConnectController ( + HandleArray[Index], + NULL, + RemainingDevicePath, + FALSE + ); + if (!EFI_ERROR(Status)) { + AtLeastOneConnected = TRUE; + } + } + } + } + } + } + + if (HandleArray != NULL) { + FreePool (HandleArray); + } + + if (AtLeastOneConnected) { + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} diff --git a/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c new file mode 100644 index 0000000000..84e4a0e6be --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c @@ -0,0 +1,1302 @@ +/** @file + BDS Lib functions which contain all the code to connect console device + +Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalBdsLib.h" +#include + + +/** + Check if we need to save the EFI variable with "ConVarName" as name + as NV type + If ConVarName is NULL, then ASSERT(). + + @param ConVarName The name of the EFI variable. + + @retval TRUE Set the EFI variable as NV type. + @retval FALSE EFI variable as NV type can be set NonNV. +**/ +BOOLEAN +IsNvNeed ( + IN CHAR16 *ConVarName + ) +{ + CHAR16 *Ptr; + + ASSERT (ConVarName != NULL); + + Ptr = ConVarName; + + // + // If the variable includes "Dev" at last, we consider + // it does not support NV attribute. + // + while (*Ptr != L'\0') { + Ptr++; + } + + if (((INTN)((UINTN)Ptr - (UINTN)ConVarName) / sizeof (CHAR16)) <= 3) { + return TRUE; + } + + if ((*(Ptr - 3) == 'D') && (*(Ptr - 2) == 'e') && (*(Ptr - 1) == 'v')) { + return FALSE; + } else { + return TRUE; + } +} + +/** + 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 = BdsLibGetVariableAndSize ( + 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) { + FreePool (FullDevicePath); + ASSERT (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 +BdsLibUpdateConsoleVariable ( + IN CHAR16 *ConVarName, + IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *VarConsole; + UINTN DevicePathSize; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath; + UINT32 Attributes; + + 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 = BdsLibGetVariableAndSize ( + ConVarName, + &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 = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath); + } + // + // Try to append customized device path to NewDevicePath. + // + if (CustomizedConDevicePath != NULL) { + if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) { + // + // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it. + // + NewDevicePath = BdsLibDelPartMatchInstance (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); + } + } + } + + // + // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV. + // + if (IsNvNeed(ConVarName)) { + // + // ConVarName has NV attribute. + // + Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE; + } else { + // + // ConVarName does not have NV attribute. + // + Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; + } + + // + // Finally, Update the variable of the default console by NewDevicePath + // + DevicePathSize = GetDevicePathSize (NewDevicePath); + Status = gRT->SetVariable ( + ConVarName, + &gEfiGlobalVariableGuid, + Attributes, + DevicePathSize, + NewDevicePath + ); + if ((DevicePathSize == 0) && (Status == EFI_NOT_FOUND)) { + Status = EFI_SUCCESS; + } + ASSERT_EFI_ERROR (Status); + + if (VarConsole == NewDevicePath) { + if (VarConsole != NULL) { + FreePool(VarConsole); + } + } else { + if (VarConsole != NULL) { + FreePool(VarConsole); + } + if (NewDevicePath != NULL) { + FreePool(NewDevicePath); + } + } + + return Status; + +} + + +/** + Connect the console device base on the variable ConVarName, if + device path of the ConVarName is multi-instance device path and + anyone of the instances is connected success, then this function + will return success. + 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 ConVarName Console related variable name, ConIn, ConOut, + ErrOut. + + @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 +BdsLibConnectConsoleVariable ( + IN CHAR16 *ConVarName + ) +{ + 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; + + Status = EFI_SUCCESS; + DeviceExist = FALSE; + + // + // Check if the console variable exist + // + StartDevicePath = BdsLibGetVariableAndSize ( + ConVarName, + &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 ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) && + ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) + || (DevicePathSubType (Instance) == MSG_USB_WWID_DP) + )) { + Status = BdsLibConnectUsbDevByShortFormDP (0xFF, Instance); + if (!EFI_ERROR (Status)) { + DeviceExist = TRUE; + } + } else { + // + // Connect the instance device path + // + Status = BdsLibConnectDevicePath (Instance); + + if (EFI_ERROR (Status)) { + // + // Delete the instance from the console varialbe + // + BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance); + } else { + DeviceExist = TRUE; + } + } + FreePool(Instance); + } while (CopyOfDevicePath != NULL); + + FreePool (StartDevicePath); + + if (!DeviceExist) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + This function will search every simpletext device in current system, + and make every simpletext device as pertantial console device. + +**/ +VOID +EFIAPI +BdsLibConnectAllConsoles ( + 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 + ); + BdsLibUpdateConsoleVariable (L"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 + ); + BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL); + BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL); + } + + if (HandleBuffer != NULL) { + FreePool(HandleBuffer); + } + + // + // Connect all console variables + // + BdsLibConnectAllDefaultConsoles (); + +} + +/** + This function will connect console device base on the console + device variable ConIn, ConOut and ErrOut. + + @retval EFI_SUCCESS At least one of the ConIn and ConOut device have + been connected success. + @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable (). + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectAllDefaultConsoles ( + VOID + ) +{ + EFI_STATUS Status; + BOOLEAN SystemTableUpdated; + + // + // Connect all default console variables + // + + // + // It seems impossible not to have any ConOut device on platform, + // so we check the status here. + // + Status = BdsLibConnectConsoleVariable (L"ConOut"); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Insert the performance probe for Console Out + // + PERF_START (NULL, "ConOut", "BDS", 1); + PERF_END (NULL, "ConOut", "BDS", 0); + + // + // Because possibly the platform is legacy free, in such case, + // ConIn devices (Serial Port and PS2 Keyboard ) does not exist, + // so we need not check the status. + // + BdsLibConnectConsoleVariable (L"ConIn"); + + // + // The _ModuleEntryPoint err out var is legal. + // + BdsLibConnectConsoleVariable (L"ErrOut"); + + 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 + ); + } + + return EFI_SUCCESS; + +} + +/** + This function will connect console device except ConIn base on the console + device variable ConOut and ErrOut. + + @retval EFI_SUCCESS At least one of the ConOut device have + been connected success. + @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable (). + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectAllDefaultConsolesWithOutConIn ( + VOID + ) +{ + EFI_STATUS Status; + BOOLEAN SystemTableUpdated; + + // + // Connect all default console variables except ConIn + // + + // + // It seems impossible not to have any ConOut device on platform, + // so we check the status here. + // + Status = BdsLibConnectConsoleVariable (L"ConOut"); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Insert the performance probe for Console Out + // + PERF_START (NULL, "ConOut", "BDS", 1); + PERF_END (NULL, "ConOut", "BDS", 0); + + // + // The _ModuleEntryPoint err out var is legal. + // + BdsLibConnectConsoleVariable (L"ErrOut"); + + SystemTableUpdated = FALSE; + // + // Fill console handles in System Table if no console device assignd. + // + 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 + ); + } + + return EFI_SUCCESS; + +} + +/** + 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; + } + // + // BMP file may has padding data between the bmp header section and the bmp data section. + // + 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; + } + + // + // Currently only support BMP format. + // + if (Format != EfiBadgingFormatBMP) { + if (ImageData != NULL) { + FreePool (ImageData); + } + continue; + } + } 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; + if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { + Attribute = EfiBadgingDisplayAttributeCenter; + } else { + Attribute = EfiBadgingDisplayAttributeCustomized; + } + } + + if (Blt != NULL) { + FreePool (Blt); + } + 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; + + case EfiBadgingDisplayAttributeCustomized: + DestX = (SizeOfX - Width) / 2; + DestY = ((SizeOfY * 382) / 1000) - 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; +} + diff --git a/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c new file mode 100644 index 0000000000..971188bd0a --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c @@ -0,0 +1,1484 @@ +/** @file + Misc BDS library function + +Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalBdsLib.h" + + +#define MAX_STRING_LEN 200 + +BOOLEAN mFeaturerSwitch = TRUE; +BOOLEAN mResetRequired = FALSE; + +extern UINT16 gPlatformBootTimeOutDefault; + +/** + 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 +EFIAPI +BdsLibLoadDrivers ( + IN LIST_ENTRY *BdsDriverLists + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + BDS_COMMON_OPTION *Option; + EFI_HANDLE ImageHandle; + EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; + UINTN ExitDataSize; + CHAR16 *ExitData; + BOOLEAN ReconnectAll; + + ReconnectAll = FALSE; + + // + // Process the driver option + // + for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) { + Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); + + // + // If a load option is not marked as LOAD_OPTION_ACTIVE, + // the boot manager will not automatically load the option. + // + if (!IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_ACTIVE)) { + 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 (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) { + ReconnectAll = TRUE; + } + + // + // Make sure the driver path is connected. + // + BdsLibConnectDevicePath (Option->DevicePath); + + // + // Load and start the image that Driver#### describes + // + Status = gBS->LoadImage ( + FALSE, + gImageHandle, + Option->DevicePath, + 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; + } + + if (Option->LoadOptionsSize != 0) { + ImageInfo->LoadOptionsSize = Option->LoadOptionsSize; + ImageInfo->LoadOptions = Option->LoadOptions; + } + // + // Before calling the image, enable the Watchdog Timer for + // the 5 Minute period + // + gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL); + + Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData); + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Driver Return Status = %r\n", 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) { + BdsLibDisconnectAllEfi (); + BdsLibConnectAll (); + } + +} + +/** + Get the Option Number that does not used. + Try to locate the specific option variable one by one utile find a free number. + + @param VariableName Indicate if the boot#### or driver#### option + + @return The Minimal Free Option Number + +**/ +UINT16 +BdsLibGetFreeOptionNumber ( + IN CHAR16 *VariableName + ) +{ + UINTN Index; + CHAR16 StrTemp[10]; + UINT16 *OptionBuffer; + UINTN OptionSize; + + // + // Try to find the minimum free number from 0, 1, 2, 3.... + // + Index = 0; + do { + if (*VariableName == 'B') { + UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Boot%04x", Index); + } else { + UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Driver%04x", Index); + } + // + // try if the option number is used + // + OptionBuffer = BdsLibGetVariableAndSize ( + StrTemp, + &gEfiGlobalVariableGuid, + &OptionSize + ); + if (OptionBuffer == NULL) { + break; + } + Index++; + } while (TRUE); + + return ((UINT16) Index); +} + + +/** + This function will register the new boot#### or driver#### option base on + the VariableName. The new registered boot#### or driver#### will be linked + to BdsOptionList and also update to the VariableName. After the boot#### or + driver#### updated, the BootOrder or DriverOrder will also be updated. + + @param BdsOptionList The header of the boot#### or driver#### link list + @param DevicePath The device path which the boot#### or driver#### + option present + @param String The description of the boot#### or driver#### + @param VariableName Indicate if the boot#### or driver#### option + + @retval EFI_SUCCESS The boot#### or driver#### have been success + registered + @retval EFI_STATUS Return the status of gRT->SetVariable (). + +**/ +EFI_STATUS +EFIAPI +BdsLibRegisterNewOption ( + IN LIST_ENTRY *BdsOptionList, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CHAR16 *String, + IN CHAR16 *VariableName + ) +{ + EFI_STATUS Status; + UINTN Index; + UINT16 RegisterOptionNumber; + UINT16 *TempOptionPtr; + UINTN TempOptionSize; + UINT16 *OptionOrderPtr; + VOID *OptionPtr; + UINTN OptionSize; + UINT8 *TempPtr; + EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath; + CHAR16 *Description; + CHAR16 OptionName[10]; + BOOLEAN UpdateDescription; + UINT16 BootOrderEntry; + UINTN OrderItemNum; + + + OptionPtr = NULL; + OptionSize = 0; + TempPtr = NULL; + OptionDevicePath = NULL; + Description = NULL; + OptionOrderPtr = NULL; + UpdateDescription = FALSE; + Status = EFI_SUCCESS; + ZeroMem (OptionName, sizeof (OptionName)); + + TempOptionSize = 0; + TempOptionPtr = BdsLibGetVariableAndSize ( + VariableName, + &gEfiGlobalVariableGuid, + &TempOptionSize + ); + // + // Compare with current option variable if the previous option is set in global variable. + // + for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) { + // + // TempOptionPtr must not be NULL if we have non-zero TempOptionSize. + // + ASSERT (TempOptionPtr != NULL); + + if (*VariableName == 'B') { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]); + } else { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]); + } + + OptionPtr = BdsLibGetVariableAndSize ( + OptionName, + &gEfiGlobalVariableGuid, + &OptionSize + ); + if (OptionPtr == NULL) { + continue; + } + + // + // Validate the variable. + // + if (!ValidateOption(OptionPtr, OptionSize)) { + continue; + } + + TempPtr = OptionPtr; + TempPtr += sizeof (UINT32) + sizeof (UINT16); + Description = (CHAR16 *) TempPtr; + TempPtr += StrSize ((CHAR16 *) TempPtr); + OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr; + + // + // Notes: the description may will change base on the GetStringToken + // + if (CompareMem (OptionDevicePath, DevicePath, GetDevicePathSize (OptionDevicePath)) == 0) { + if (CompareMem (Description, String, StrSize (Description)) == 0) { + // + // Got the option, so just return + // + FreePool (OptionPtr); + FreePool (TempOptionPtr); + return EFI_SUCCESS; + } else { + // + // Option description changed, need update. + // + UpdateDescription = TRUE; + FreePool (OptionPtr); + break; + } + } + + FreePool (OptionPtr); + } + + OptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (String); + OptionSize += GetDevicePathSize (DevicePath); + OptionPtr = AllocateZeroPool (OptionSize); + ASSERT (OptionPtr != NULL); + + TempPtr = OptionPtr; + *(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE; + TempPtr += sizeof (UINT32); + *(UINT16 *) TempPtr = (UINT16) GetDevicePathSize (DevicePath); + TempPtr += sizeof (UINT16); + CopyMem (TempPtr, String, StrSize (String)); + TempPtr += StrSize (String); + CopyMem (TempPtr, DevicePath, GetDevicePathSize (DevicePath)); + + if (UpdateDescription) { + // + // The number in option#### to be updated. + // In this case, we must have non-NULL TempOptionPtr. + // + ASSERT (TempOptionPtr != NULL); + RegisterOptionNumber = TempOptionPtr[Index]; + } else { + // + // The new option#### number + // + RegisterOptionNumber = BdsLibGetFreeOptionNumber(VariableName); + } + + if (*VariableName == 'B') { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber); + } else { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber); + } + + Status = gRT->SetVariable ( + OptionName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + OptionSize, + OptionPtr + ); + // + // Return if only need to update a changed description or fail to set option. + // + if (EFI_ERROR (Status) || UpdateDescription) { + FreePool (OptionPtr); + if (TempOptionPtr != NULL) { + FreePool (TempOptionPtr); + } + return Status; + } + + FreePool (OptionPtr); + + // + // Update the option order variable + // + + // + // If no option order + // + if (TempOptionSize == 0) { + BootOrderEntry = 0; + Status = gRT->SetVariable ( + VariableName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (UINT16), + &BootOrderEntry + ); + if (TempOptionPtr != NULL) { + FreePool (TempOptionPtr); + } + return Status; + } + + // + // TempOptionPtr must not be NULL if TempOptionSize is not zero. + // + ASSERT (TempOptionPtr != NULL); + // + // Append the new option number to the original option order + // + OrderItemNum = (TempOptionSize / sizeof (UINT16)) + 1 ; + OptionOrderPtr = AllocateZeroPool ( OrderItemNum * sizeof (UINT16)); + ASSERT (OptionOrderPtr!= NULL); + CopyMem (OptionOrderPtr, TempOptionPtr, (OrderItemNum - 1) * sizeof (UINT16)); + + OptionOrderPtr[Index] = RegisterOptionNumber; + + Status = gRT->SetVariable ( + VariableName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + OrderItemNum * sizeof (UINT16), + OptionOrderPtr + ); + FreePool (TempOptionPtr); + FreePool (OptionOrderPtr); + + return Status; +} + +/** + 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 < END_DEVICE_PATH_LENGTH) { + 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 byte length 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); +} + +/** + 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' + + @param Char The input char which need to change to a hex number. + +**/ +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; +} + +/** + Build the boot#### or driver#### option from the VariableName, the + build boot#### or driver#### will also be linked to BdsCommonOptionList. + + @param BdsCommonOptionList The header of the boot#### or driver#### option + link list + @param VariableName EFI Variable name indicate if it is boot#### or + driver#### + + @retval BDS_COMMON_OPTION Get the option just been created + @retval NULL Failed to get the new option + +**/ +BDS_COMMON_OPTION * +EFIAPI +BdsLibVariableToOption ( + IN OUT LIST_ENTRY *BdsCommonOptionList, + IN CHAR16 *VariableName + ) +{ + UINT32 Attribute; + UINT16 FilePathSize; + UINT8 *Variable; + UINT8 *TempPtr; + UINTN VariableSize; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BDS_COMMON_OPTION *Option; + VOID *LoadOptions; + UINT32 LoadOptionsSize; + CHAR16 *Description; + UINT8 NumOff; + + // + // Read the variable. We will never free this data. + // + Variable = BdsLibGetVariableAndSize ( + VariableName, + &gEfiGlobalVariableGuid, + &VariableSize + ); + if (Variable == NULL) { + return NULL; + } + + // + // Validate Boot#### variable data. + // + if (!ValidateOption(Variable, VariableSize)) { + return NULL; + } + + // + // 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 + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr; + TempPtr += FilePathSize; + + // + // Get load opion data. + // + LoadOptions = TempPtr; + LoadOptionsSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable)); + + // + // The Console variables may have multiple device paths, so make + // an Entry for each one. + // + Option = AllocateZeroPool (sizeof (BDS_COMMON_OPTION)); + if (Option == NULL) { + return NULL; + } + + Option->Signature = BDS_LOAD_OPTION_SIGNATURE; + Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath)); + ASSERT(Option->DevicePath != NULL); + CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath)); + + Option->Attribute = Attribute; + Option->Description = AllocateZeroPool (StrSize (Description)); + ASSERT(Option->Description != NULL); + CopyMem (Option->Description, Description, StrSize (Description)); + + Option->LoadOptions = AllocateZeroPool (LoadOptionsSize); + ASSERT(Option->LoadOptions != NULL); + CopyMem (Option->LoadOptions, LoadOptions, LoadOptionsSize); + Option->LoadOptionsSize = LoadOptionsSize; + + // + // 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. + // + if (*VariableName == 'B') { + NumOff = (UINT8) (sizeof (L"Boot") / sizeof (CHAR16) - 1); + Option->BootCurrent = (UINT16) (CharToUint (VariableName[NumOff+0]) * 0x1000) + + (UINT16) (CharToUint (VariableName[NumOff+1]) * 0x100) + + (UINT16) (CharToUint (VariableName[NumOff+2]) * 0x10) + + (UINT16) (CharToUint (VariableName[NumOff+3]) * 0x1); + } + InsertTailList (BdsCommonOptionList, &Option->Link); + FreePool (Variable); + return Option; +} + +/** + 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_STATUS +EFIAPI +BdsLibBuildOptionFromVar ( + IN LIST_ENTRY *BdsCommonOptionList, + IN CHAR16 *VariableName + ) +{ + UINT16 *OptionOrder; + UINTN OptionOrderSize; + UINTN Index; + BDS_COMMON_OPTION *Option; + CHAR16 OptionName[20]; + + // + // Zero Buffer in order to get all BOOT#### variables + // + ZeroMem (OptionName, sizeof (OptionName)); + + // + // Read the BootOrder, or DriverOrder variable. + // + OptionOrder = BdsLibGetVariableAndSize ( + VariableName, + &gEfiGlobalVariableGuid, + &OptionOrderSize + ); + if (OptionOrder == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) { + if (*VariableName == 'B') { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionOrder[Index]); + } else { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionOrder[Index]); + } + + Option = BdsLibVariableToOption (BdsCommonOptionList, OptionName); + if (Option != NULL) { + Option->BootCurrent = OptionOrder[Index]; + } + } + + FreePool (OptionOrder); + + return EFI_SUCCESS; +} + +/** + Get boot mode by looking up configuration table and parsing HOB list + + @param BootMode Boot mode from PEI handoff HOB. + + @retval EFI_SUCCESS Successfully get boot mode + +**/ +EFI_STATUS +EFIAPI +BdsLibGetBootMode ( + OUT EFI_BOOT_MODE *BootMode + ) +{ + *BootMode = GetBootModeHob (); + + return EFI_SUCCESS; +} + +/** + 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 +BdsLibGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VariableSize + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + VOID *Buffer; + + Buffer = NULL; + + // + // Pass in a zero size buffer to find the required buffer size. + // + BufferSize = 0; + Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Allocate the buffer to return + // + Buffer = AllocateZeroPool (BufferSize); + if (Buffer == NULL) { + *VariableSize = 0; + return 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 +BdsLibDelPartMatchInstance ( + 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; + UINTN Size; + + 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) { + + Size = (SingleDpSize < InstanceSize) ? SingleDpSize : InstanceSize; + + if ((CompareMem (Instance, Single, Size) != 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 +BdsLibMatchDevicePaths ( + 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; +} + +/** + This function prints a series of strings. + + @param ConOut Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL + @param ... A variable argument list containing series of + strings, the last string must be NULL. + + @retval EFI_SUCCESS Success print out the string using ConOut. + @retval EFI_STATUS Return the status of the ConOut->OutputString (). + +**/ +EFI_STATUS +EFIAPI +BdsLibOutputStrings ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut, + ... + ) +{ + VA_LIST Args; + EFI_STATUS Status; + CHAR16 *String; + + Status = EFI_SUCCESS; + VA_START (Args, ConOut); + + while (!EFI_ERROR (Status)) { + // + // If String is NULL, then it's the end of the list + // + String = VA_ARG (Args, CHAR16 *); + if (String == NULL) { + break; + } + + Status = ConOut->OutputString (ConOut, String); + + if (EFI_ERROR (Status)) { + break; + } + } + + VA_END(Args); + return Status; +} + +// +// Following are BDS Lib functions which contain all the code about setup browser reset reminder feature. +// Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser if +// user change any option setting which needs a reset to be effective, and the reset will be applied according to the user selection. +// + + +/** + Enable the setup browser reset reminder feature. + This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it. + +**/ +VOID +EFIAPI +EnableResetReminderFeature ( + VOID + ) +{ + mFeaturerSwitch = TRUE; +} + + +/** + Disable the setup browser reset reminder feature. + This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it. + +**/ +VOID +EFIAPI +DisableResetReminderFeature ( + VOID + ) +{ + mFeaturerSwitch = FALSE; +} + + +/** + Record the info that a reset is required. + A module boolean variable is used to record whether a reset is required. + +**/ +VOID +EFIAPI +EnableResetRequired ( + VOID + ) +{ + mResetRequired = TRUE; +} + + +/** + Record the info that no reset is required. + A module boolean variable is used to record whether a reset is required. + +**/ +VOID +EFIAPI +DisableResetRequired ( + VOID + ) +{ + mResetRequired = FALSE; +} + + +/** + Check whether platform policy enable the reset reminder feature. The default is enabled. + +**/ +BOOLEAN +EFIAPI +IsResetReminderFeatureEnable ( + VOID + ) +{ + return mFeaturerSwitch; +} + + +/** + Check if user changed any option setting which needs a system reset to be effective. + +**/ +BOOLEAN +EFIAPI +IsResetRequired ( + VOID + ) +{ + return mResetRequired; +} + + +/** + Check whether a reset is needed, and finish the reset reminder feature. + If a reset is needed, Popup a menu to notice user, and finish the feature + according to the user selection. + +**/ +VOID +EFIAPI +SetupResetReminder ( + VOID + ) +{ + EFI_INPUT_KEY Key; + CHAR16 *StringBuffer1; + CHAR16 *StringBuffer2; + + + // + //check any reset required change is applied? if yes, reset system + // + if (IsResetReminderFeatureEnable ()) { + if (IsResetRequired ()) { + + StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16)); + ASSERT (StringBuffer1 != NULL); + StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16)); + ASSERT (StringBuffer2 != NULL); + StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now."); + StrCpy (StringBuffer2, L"Press ENTER to reset"); + // + // Popup a menu to notice user + // + do { + CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + FreePool (StringBuffer1); + FreePool (StringBuffer2); + + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + } + } +} + +/** + 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 +EFIAPI +BdsLibGetImageHeader ( + 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 +BdsSetMemoryTypeInformationVariable ( + 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 && PcdGetBool (PcdResetOnMemoryTypeInformationChange)) { + DEBUG ((EFI_D_INFO, "Memory Type Information settings change. Warm Reset!!!\n")); + gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); + } + } +} + +/** + This routine is kept for backward compatibility. +**/ +VOID +EFIAPI +BdsLibSaveMemoryTypeInformation ( + VOID + ) +{ +} + + +/** + 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 +EFIAPI +BdsLibUserIdentify ( + 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); +} + diff --git a/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c new file mode 100644 index 0000000000..2f22e7df7f --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c @@ -0,0 +1,33 @@ +/** @file + BDS internal function define the default device path string, it can be + replaced by platform device path. + +Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalBdsLib.h" + +/** + 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 + ) +{ + return ConvertDevicePathToText (DevPath, TRUE, TRUE); +} diff --git a/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf new file mode 100644 index 0000000000..2fb9916aa5 --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf @@ -0,0 +1,114 @@ +## @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) 2007 - 2013, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = GenericBdsLib + FILE_GUID = e405ec31-ccaa-4dd4-83e8-0aec01703f7e + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = GenericBdsLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION + CONSTRUCTOR = GenericBdsLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DevicePath.c + Performance.c + BdsConnect.c + BdsMisc.c + BdsConsole.c + BdsBoot.c + InternalBdsLib.h + String.h + String.c + GenericBdsStrings.uni + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + DevicePathLib + PeCoffGetEntryPointLib + BaseLib + HobLib + UefiRuntimeServicesTableLib + DxeServicesTableLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + PrintLib + PcdLib + PerformanceLib + TimerLib + DxeServicesLib + HiiLib + ReportStatusCodeLib + +[Guids] + gEfiMemoryTypeInformationGuid ## CONSUMES ## GUID (The identifier of memory type information type in system table) + gEfiGlobalVariableGuid ## SOMETIMES_PRODUCES ## Variable:L"BootCurrent" (The boot option of current boot) + gEfiFileInfoGuid ## CONSUMES ## GUID + gPerformanceProtocolGuid ## SOMETIMES_PRODUCES ## Variable:L"PerfDataMemAddr" (The ACPI address of performance data) + gEfiUartDevicePathGuid ## CONSUMES ## GUID (Identify the device path for UARD device) + gLastEnumLangGuid ## SOMETIMES_PRODUCES ## Variable:L"LastEnumLang" (Platform language at last time enumeration.) + gHdBootDevicePathVariablGuid ## SOMETIMES_PRODUCES ## Variable:L"HDDP" (The device path of Boot file on Hard device.) + gBdsLibStringPackageGuid ## PRODUCES ## GUID (HII String PackageList Guid) + gEfiLegacyDevOrderVariableGuid ## CONSUMES ## GUID + +[Protocols] + gEfiSimpleFileSystemProtocolGuid # PROTOCOL CONSUMES + gEfiLoadFileProtocolGuid # PROTOCOL CONSUMES + gEfiSimpleTextOutProtocolGuid # PROTOCOL CONSUMES + gEfiPciIoProtocolGuid # PROTOCOL CONSUMES + gEfiLoadedImageProtocolGuid # PROTOCOL CONSUMES + gEfiSimpleNetworkProtocolGuid # PROTOCOL CONSUMES + gEfiDebugPortProtocolGuid # PROTOCOL CONSUMES + gEfiSimpleTextInProtocolGuid # PROTOCOL CONSUMES + gEfiBlockIoProtocolGuid # PROTOCOL CONSUMES + gEfiFirmwareVolume2ProtocolGuid # PROTOCOL CONSUMES + gEfiLegacyBiosProtocolGuid # PROTOCOL SOMETIMES_CONSUMES + gEfiCpuArchProtocolGuid # PROTOCOL CONSUMES + gEfiDevicePathProtocolGuid # PROTOCOL CONSUMES + gEfiAcpiS3SaveProtocolGuid # PROTOCOL CONSUMES + gEfiGraphicsOutputProtocolGuid # PROTOCOL SOMETIMES_CONSUMES + gEfiUgaDrawProtocolGuid |gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport # PROTOCOL SOMETIMES_CONSUMES + gEfiOEMBadgingProtocolGuid # PROTOCOL CONSUMES + gEfiHiiFontProtocolGuid # PROTOCOL CONSUMES + gEfiUserManagerProtocolGuid # PROTOCOL CONSUMES + gEfiUsbIoProtocolGuid # PROTOCOL SOMETIMES_CONSUMES + gEfiBootLogoProtocolGuid # PROTOCOL SOMETIMES_CONSUMES + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootlogoOnlyEnable + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange + gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderLoad + gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderStart + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile diff --git a/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsStrings.uni b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsStrings.uni new file mode 100644 index 0000000000000000000000000000000000000000..81621d68886e0de8865a94ecbf9302c5921bc176 GIT binary patch literal 3868 zcmd6qUr!oQ5XI-YNx#DeU)n~n?W1X%ieM!w5W(6$83aL66tbY!Puy?O_IKtAyQ^Tb z@r7)5@83Cd=FHq>`S*9rbiLz>?5p){Xd}C@*Y?WiBWBb6mdz|?&$SI$>9JE5*W5Gi zF}*4CeR?r%nRd)dWDT1vb_BbrbsZ_0FJ(NXz3zfCv3uV?uuDgLgZ*2OKiYfyz#Um} zG5TPe^lPx0!Ei)h2r(FXb{0%Ztn9F^9f~SoD}oriDR*qQJbPBMPegNUUosrqa2a~U z6LyZV7y1?U9enp_XY9D}aTmU0)+WAok6qC4%K6CCklqNibmSf8Wj|uIOHcZWPvSxL z%7bQZxs|_;o%7V(jq?zC!bO_IFj1Uyp5i9P**uQPWMWsgmQ@%ZX1Ju;-nkxKo zJjAO!N|B(MyiFM^@^hHZD@a+1Oxh}fJ}V(Z;{BUl5nR)}vf4yM)}dA+FoXU0K?QM| zWzfEJwVU_#w%YQQF!R|q7NZUFp{gGEsZgEhQeKP1CO-v` zwXVEP$yLE^m)rHpe$n2cHjJupTFxx5O1tPM z4Zm|gjba(IRVoFHEizFd7Y%AG%W%d6PFpWBK@SwlCyX_9Lh zzg3FuQ+Y9GNbe-Qq4hhsUYf0Dm{&Eu7s@G}62;WZquLy)f?Btzrr+%KQf)QEysGKF z*7B2{)hmqhsFonDuWrwA%&XiHstIqIZu#o%$bW~reoEK1;-2G}SGhWGv^HNS`Vu*K zqFLvg5 M*7pS0VVj5df7X)&Z2$lO literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h new file mode 100644 index 0000000000..80b1f49a90 --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h @@ -0,0 +1,150 @@ +/** @file + BDS library definition, include the file and data structure + +Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _INTERNAL_BDS_LIB_H_ +#define _INTERNAL_BDS_LIB_H_ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + +/** + + 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 +EFIAPI +BdsLibGetImageHeader ( + IN EFI_HANDLE Device, + IN CHAR16 *FileName, + OUT EFI_IMAGE_DOS_HEADER *DosHeader, + OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr + ); + +/** + This routine adjust the memory information for different memory type and + save them into the variables for next boot. +**/ +VOID +BdsSetMemoryTypeInformationVariable ( + VOID + ); + +/** + Validate the EFI Boot#### or Driver#### 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 + ); + +#endif // _BDS_LIB_H_ diff --git a/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c new file mode 100644 index 0000000000..047d2a7dbc --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c @@ -0,0 +1,358 @@ +/** @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) 2004 - 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalBdsLib.h" + +PERF_HEADER mPerfHeader; +PERF_DATA mPerfData; +EFI_PHYSICAL_ADDRESS mAcpiLowMemoryBase = 0x0FFFFFFFFULL; + +/** + 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 ; +} + +/** + + 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; + UINTN VarSize; + + // + // Record the performance data for End of BDS + // + PERF_END(NULL, "BDS", NULL, 0); + + // + // 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; + } + + if (mAcpiLowMemoryBase == 0x0FFFFFFFF) { + VarSize = sizeof (EFI_PHYSICAL_ADDRESS); + Status = gRT->GetVariable ( + L"PerfDataMemAddr", + &gPerformanceProtocolGuid, + NULL, + &VarSize, + &mAcpiLowMemoryBase + ); + if (EFI_ERROR (Status)) { + // + // Fail to get the variable, return. + // + return; + } + } + + // + // 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 = (UINT32) (PERF_DATA_MAX_LENGTH - 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/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/String.c b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/String.c new file mode 100644 index 0000000000..762871605d --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/String.c @@ -0,0 +1,32 @@ +/** @file + String support + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include "String.h" + +/** + Get string by string id from HII Interface + + + @param Id String ID. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +CHAR16 * +BdsLibGetStringById ( + IN EFI_STRING_ID Id + ) +{ + return HiiGetString (gBdsLibStringPackHandle, Id, NULL); +} diff --git a/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/String.h b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/String.h new file mode 100644 index 0000000000..13b745de87 --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/String.h @@ -0,0 +1,48 @@ +/** @file + String support + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _STRING_H_ +#define _STRING_H_ + +#include +#include +#include +#include +#include + +extern EFI_HII_HANDLE gBdsLibStringPackHandle; + +// +// This is the VFR compiler generated header file which defines the +// string identifiers. +// + +extern UINT8 GenericBdsLibStrings[]; + +/** + Get string by string id from HII Interface + + + @param Id String ID. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +CHAR16 * +BdsLibGetStringById ( + IN EFI_STRING_ID Id + ); + +#endif // _STRING_H_ diff --git a/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ComponentName.c b/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ComponentName.c new file mode 100644 index 0000000000..9ad1726599 --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ComponentName.c @@ -0,0 +1,776 @@ +/** @file + UEFI Component Name(2) protocol implementation for ConSplitter driver. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "ConSplitter.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gConSplitterConInComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterConInComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gConSplitterConInComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) ConSplitterComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) ConSplitterConInComponentNameGetControllerName, + "en" +}; + + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gConSplitterSimplePointerComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterSimplePointerComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gConSplitterSimplePointerComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) ConSplitterComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) ConSplitterSimplePointerComponentNameGetControllerName, + "en" +}; + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gConSplitterAbsolutePointerComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterAbsolutePointerComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gConSplitterAbsolutePointerComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) ConSplitterComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) ConSplitterAbsolutePointerComponentNameGetControllerName, + "en" +}; + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gConSplitterConOutComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterConOutComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gConSplitterConOutComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) ConSplitterComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) ConSplitterConOutComponentNameGetControllerName, + "en" +}; + + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gConSplitterStdErrComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterStdErrComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gConSplitterStdErrComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) ConSplitterComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) ConSplitterStdErrComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mConSplitterDriverNameTable[] = { + { + "eng;en", + (CHAR16 *) L"Console Splitter Driver" + }, + { + NULL, + NULL + } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mConSplitterConInControllerNameTable[] = { + { + "eng;en", + (CHAR16 *) L"Primary Console Input Device" + }, + { + NULL, + NULL + } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mConSplitterSimplePointerControllerNameTable[] = { + { + "eng;en", + (CHAR16 *) L"Primary Simple Pointer Device" + }, + { + NULL, + NULL + } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mConSplitterAbsolutePointerControllerNameTable[] = { + { + "eng;en", + (CHAR16 *)L"Primary Absolute Pointer Device" + }, + { + NULL, + NULL + } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mConSplitterConOutControllerNameTable[] = { + { + "eng;en", + (CHAR16 *) L"Primary Console Output Device" + }, + { + NULL, + NULL + } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mConSplitterStdErrControllerNameTable[] = { + { + "eng;en", + (CHAR16 *) L"Primary Standard Error Device" + }, + { + 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 +ConSplitterComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mConSplitterDriverNameTable, + DriverName, + (BOOLEAN)((This == &gConSplitterConInComponentName) || + (This == &gConSplitterSimplePointerComponentName) || + (This == &gConSplitterAbsolutePointerComponentName) || + (This == &gConSplitterConOutComponentName) || + (This == &gConSplitterStdErrComponentName)) + ); +} + +/** + Tests whether a controller handle is being managed by a specific driver and + the child handle is a child device of the controller. + + @param ControllerHandle A handle for a controller to test. + @param DriverBindingHandle Specifies the driver binding handle for the + driver. + @param ProtocolGuid Specifies the protocol that the driver specified + by DriverBindingHandle opens in its Start() + function. + @param ChildHandle A child handle to test. + @param ConsumsedGuid Supplies the protocol that the child controller + opens on its parent controller. + + @retval EFI_SUCCESS ControllerHandle is managed by the driver + specifed by DriverBindingHandle and ChildHandle + is a child of the ControllerHandle. + @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver + specifed by DriverBindingHandle. + @retval EFI_UNSUPPORTED ChildHandle is not a child of the + ControllerHandle. + +**/ +EFI_STATUS +ConSplitterTestControllerHandles ( + IN CONST EFI_HANDLE ControllerHandle, + IN CONST EFI_HANDLE DriverBindingHandle, + IN CONST EFI_GUID *ProtocolGuid, + IN EFI_HANDLE ChildHandle, + IN CONST EFI_GUID *ConsumsedGuid + ) +{ + EFI_STATUS Status; + + // + // here ChildHandle is not an Optional parameter. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Tests whether a controller handle is being managed by a specific driver. + // + Status = EfiTestManagedDevice ( + ControllerHandle, + DriverBindingHandle, + ProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Tests whether a child handle is a child device of the controller. + // + Status = EfiTestChildHandle ( + ControllerHandle, + ChildHandle, + ConsumsedGuid + ); + + return Status; +} + +/** + 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 NULL. + + @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 +ConSplitterConInComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + + Status = ConSplitterTestControllerHandles ( + ControllerHandle, + gConSplitterConInDriverBinding.DriverBindingHandle, + &gEfiConsoleInDeviceGuid, + ChildHandle, + &gEfiConsoleInDeviceGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mConSplitterConInControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gConSplitterConInComponentName) + ); +} + +/** + 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 NULL. + + @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 +ConSplitterSimplePointerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + + Status = ConSplitterTestControllerHandles ( + ControllerHandle, + gConSplitterSimplePointerDriverBinding.DriverBindingHandle, + &gEfiSimplePointerProtocolGuid, + ChildHandle, + &gEfiSimplePointerProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mConSplitterSimplePointerControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gConSplitterSimplePointerComponentName) + ); +} + + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL + instance. + @param ControllerHandle 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 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 A pointer to RFC4646 language identifier. This is + the language of the controller name that 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. + @param ControllerName 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 NULL. + @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 +ConSplitterAbsolutePointerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + + Status = ConSplitterTestControllerHandles ( + ControllerHandle, + gConSplitterAbsolutePointerDriverBinding.DriverBindingHandle, + &gEfiAbsolutePointerProtocolGuid, + ChildHandle, + &gEfiAbsolutePointerProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mConSplitterAbsolutePointerControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gConSplitterAbsolutePointerComponentName) + ); +} + +/** + 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 NULL. + + @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 +ConSplitterConOutComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + + Status = ConSplitterTestControllerHandles ( + ControllerHandle, + gConSplitterConOutDriverBinding.DriverBindingHandle, + &gEfiConsoleOutDeviceGuid, + ChildHandle, + &gEfiConsoleOutDeviceGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mConSplitterConOutControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gConSplitterConOutComponentName) + ); +} + +/** + 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 NULL. + + @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 +ConSplitterStdErrComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + + Status = ConSplitterTestControllerHandles ( + ControllerHandle, + gConSplitterStdErrDriverBinding.DriverBindingHandle, + &gEfiStandardErrorDeviceGuid, + ChildHandle, + &gEfiStandardErrorDeviceGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mConSplitterStdErrControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gConSplitterStdErrComponentName) + ); +} diff --git a/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c b/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c new file mode 100644 index 0000000000..79e6153985 --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c @@ -0,0 +1,4776 @@ +/** @file + Console Splitter Driver. Any Handle that attatched console I/O protocols + (Console In device, Console Out device, Console Error device, Simple Pointer + protocol, Absolute Pointer protocol) can be bound by this driver. + + So far it works like any other driver by opening a SimpleTextIn and/or + SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big + difference is this driver does not layer a protocol on the passed in + handle, or construct a child handle like a standard device or bus driver. + This driver produces three virtual handles as children, one for console input + splitter, one for console output splitter and one for error output splitter. + These 3 virtual handles would be installed on gST. + + Each virtual handle, that supports the Console I/O protocol, will be produced + in the driver entry point. The virtual handle are added on driver entry and + never removed. Such design ensures sytem function well during none console + device situation. + +Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "ConSplitter.h" + +// +// Identify if ConIn is connected in PcdConInConnectOnDemand enabled mode. +// default not connect +// +BOOLEAN mConInIsConnect = FALSE; + +// +// Text In Splitter Private Data template +// +GLOBAL_REMOVE_IF_UNREFERENCED TEXT_IN_SPLITTER_PRIVATE_DATA mConIn = { + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE, + (EFI_HANDLE) NULL, + + { + ConSplitterTextInReset, + ConSplitterTextInReadKeyStroke, + (EFI_EVENT) NULL + }, + 0, + (EFI_SIMPLE_TEXT_INPUT_PROTOCOL **) NULL, + 0, + + { + ConSplitterTextInResetEx, + ConSplitterTextInReadKeyStrokeEx, + (EFI_EVENT) NULL, + ConSplitterTextInSetState, + ConSplitterTextInRegisterKeyNotify, + ConSplitterTextInUnregisterKeyNotify + }, + 0, + (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **) NULL, + 0, + { + (LIST_ENTRY *) NULL, + (LIST_ENTRY *) NULL + }, + + { + ConSplitterSimplePointerReset, + ConSplitterSimplePointerGetState, + (EFI_EVENT) NULL, + (EFI_SIMPLE_POINTER_MODE *) NULL + }, + { + 0x10000, + 0x10000, + 0x10000, + TRUE, + TRUE + }, + 0, + (EFI_SIMPLE_POINTER_PROTOCOL **) NULL, + 0, + + { + ConSplitterAbsolutePointerReset, + ConSplitterAbsolutePointerGetState, + (EFI_EVENT) NULL, + (EFI_ABSOLUTE_POINTER_MODE *) NULL + }, + { + 0, // AbsoluteMinX + 0, // AbsoluteMinY + 0, // AbsoluteMinZ + 0x10000, // AbsoluteMaxX + 0x10000, // AbsoluteMaxY + 0x10000, // AbsoluteMaxZ + 0 // Attributes + }, + 0, + (EFI_ABSOLUTE_POINTER_PROTOCOL **) NULL, + 0, + FALSE, + + FALSE, + FALSE +}; + + +// +// Uga Draw Protocol Private Data template +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UGA_DRAW_PROTOCOL mUgaDrawProtocolTemplate = { + ConSplitterUgaDrawGetMode, + ConSplitterUgaDrawSetMode, + ConSplitterUgaDrawBlt +}; + +// +// Graphics Output Protocol Private Data template +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_GRAPHICS_OUTPUT_PROTOCOL mGraphicsOutputProtocolTemplate = { + ConSplitterGraphicsOutputQueryMode, + ConSplitterGraphicsOutputSetMode, + ConSplitterGraphicsOutputBlt, + NULL +}; + + +// +// Text Out Splitter Private Data template +// +GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = { + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE, + (EFI_HANDLE) NULL, + { + ConSplitterTextOutReset, + ConSplitterTextOutOutputString, + ConSplitterTextOutTestString, + ConSplitterTextOutQueryMode, + ConSplitterTextOutSetMode, + ConSplitterTextOutSetAttribute, + ConSplitterTextOutClearScreen, + ConSplitterTextOutSetCursorPosition, + ConSplitterTextOutEnableCursor, + (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL + }, + { + 1, + 0, + 0, + 0, + 0, + FALSE, + }, + + { + NULL, + NULL, + NULL + }, + 0, + 0, + 0, + 0, + + { + NULL, + NULL, + NULL, + NULL + }, + (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL, + 0, + 0, + + 0, + (TEXT_OUT_AND_GOP_DATA *) NULL, + 0, + (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL, + 0, + (INT32 *) NULL +}; + +// +// Standard Error Text Out Splitter Data Template +// +GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = { + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE, + (EFI_HANDLE) NULL, + { + ConSplitterTextOutReset, + ConSplitterTextOutOutputString, + ConSplitterTextOutTestString, + ConSplitterTextOutQueryMode, + ConSplitterTextOutSetMode, + ConSplitterTextOutSetAttribute, + ConSplitterTextOutClearScreen, + ConSplitterTextOutSetCursorPosition, + ConSplitterTextOutEnableCursor, + (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL + }, + { + 1, + 0, + 0, + 0, + 0, + FALSE, + }, + + { + NULL, + NULL, + NULL + }, + 0, + 0, + 0, + 0, + + { + NULL, + NULL, + NULL, + NULL + }, + (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL, + 0, + 0, + + 0, + (TEXT_OUT_AND_GOP_DATA *) NULL, + 0, + (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL, + 0, + (INT32 *) NULL +}; + +// +// Driver binding instance for Console Input Device +// +EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding = { + ConSplitterConInDriverBindingSupported, + ConSplitterConInDriverBindingStart, + ConSplitterConInDriverBindingStop, + 0xa, + NULL, + NULL +}; + +// +// Driver binding instance for Console Out device +// +EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding = { + ConSplitterConOutDriverBindingSupported, + ConSplitterConOutDriverBindingStart, + ConSplitterConOutDriverBindingStop, + 0xa, + NULL, + NULL +}; + +// +// Driver binding instance for Standard Error device +// +EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding = { + ConSplitterStdErrDriverBindingSupported, + ConSplitterStdErrDriverBindingStart, + ConSplitterStdErrDriverBindingStop, + 0xa, + NULL, + NULL +}; + +// +// Driver binding instance for Simple Pointer protocol +// +EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding = { + ConSplitterSimplePointerDriverBindingSupported, + ConSplitterSimplePointerDriverBindingStart, + ConSplitterSimplePointerDriverBindingStop, + 0xa, + NULL, + NULL +}; + +// +// Driver binding instance for Absolute Pointer protocol +// +EFI_DRIVER_BINDING_PROTOCOL gConSplitterAbsolutePointerDriverBinding = { + ConSplitterAbsolutePointerDriverBindingSupported, + ConSplitterAbsolutePointerDriverBindingStart, + ConSplitterAbsolutePointerDriverBindingStop, + 0xa, + NULL, + NULL +}; + +/** + The Entry Point for module ConSplitter. The user code starts with this function. + + Installs driver module protocols and. Creates virtual device handles for ConIn, + ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol, + Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers. + Installs Graphics Output protocol and/or UGA Draw protocol if needed. + + @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 +ConSplitterDriverEntry( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gConSplitterConInDriverBinding, + ImageHandle, + &gConSplitterConInComponentName, + &gConSplitterConInComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gConSplitterSimplePointerDriverBinding, + NULL, + &gConSplitterSimplePointerComponentName, + &gConSplitterSimplePointerComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gConSplitterAbsolutePointerDriverBinding, + NULL, + &gConSplitterAbsolutePointerComponentName, + &gConSplitterAbsolutePointerComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gConSplitterConOutDriverBinding, + NULL, + &gConSplitterConOutComponentName, + &gConSplitterConOutComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gConSplitterStdErrDriverBinding, + NULL, + &gConSplitterStdErrComponentName, + &gConSplitterStdErrComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + // + // Either Graphics Output protocol or UGA Draw protocol must be supported. + // + ASSERT (FeaturePcdGet (PcdConOutGopSupport) || + FeaturePcdGet (PcdConOutUgaSupport)); + + // + // The driver creates virtual handles for ConIn, ConOut, StdErr. + // The virtual handles will always exist even if no console exist in the + // system. This is need to support hotplug devices like USB. + // + // + // Create virtual device handle for ConIn Splitter + // + Status = ConSplitterTextInConstructor (&mConIn); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mConIn.VirtualHandle, + &gEfiSimpleTextInProtocolGuid, + &mConIn.TextIn, + &gEfiSimpleTextInputExProtocolGuid, + &mConIn.TextInEx, + &gEfiSimplePointerProtocolGuid, + &mConIn.SimplePointer, + &gEfiAbsolutePointerProtocolGuid, + &mConIn.AbsolutePointer, + NULL + ); + if (!EFI_ERROR (Status)) { + // + // Update the EFI System Table with new virtual console + // and update the pointer to Simple Text Input protocol. + // + gST->ConsoleInHandle = mConIn.VirtualHandle; + gST->ConIn = &mConIn.TextIn; + } + } + // + // Create virtual device handle for ConOut Splitter + // + Status = ConSplitterTextOutConstructor (&mConOut); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mConOut.VirtualHandle, + &gEfiSimpleTextOutProtocolGuid, + &mConOut.TextOut, + NULL + ); + if (!EFI_ERROR (Status)) { + // + // Update the EFI System Table with new virtual console + // and Update the pointer to Text Output protocol. + // + gST->ConsoleOutHandle = mConOut.VirtualHandle; + gST->ConOut = &mConOut.TextOut; + } + + } + + // + // Create virtual device handle for StdErr Splitter + // + Status = ConSplitterTextOutConstructor (&mStdErr); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mStdErr.VirtualHandle, + &gEfiSimpleTextOutProtocolGuid, + &mStdErr.TextOut, + NULL + ); + if (!EFI_ERROR (Status)) { + // + // Update the EFI System Table with new virtual console + // and update the pointer to Text Output protocol. + // + gST->StandardErrorHandle = mStdErr.VirtualHandle; + gST->StdErr = &mStdErr.TextOut; + } + } + + // + // Update the CRC32 in the EFI System Table header + // + gST->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ( + (UINT8 *) &gST->Hdr, + gST->Hdr.HeaderSize, + &gST->Hdr.CRC32 + ); + + return EFI_SUCCESS; + +} + +/** + Construct console input devices' private data. + + @param ConInPrivate A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA + structure. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS Text Input Devcie's private data has been constructed. + @retval other Failed to construct private data. + +**/ +EFI_STATUS +ConSplitterTextInConstructor ( + TEXT_IN_SPLITTER_PRIVATE_DATA *ConInPrivate + ) +{ + EFI_STATUS Status; + + // + // Allocate buffer for Simple Text Input device + // + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *), + &ConInPrivate->TextInListCount, + (VOID **) &ConInPrivate->TextInList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Create Event to wait for a key + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + ConSplitterTextInWaitForKey, + ConInPrivate, + &ConInPrivate->TextIn.WaitForKey + ); + ASSERT_EFI_ERROR (Status); + + // + // Allocate buffer for Simple Text Input Ex device + // + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *), + &ConInPrivate->TextInExListCount, + (VOID **) &ConInPrivate->TextInExList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Create Event to wait for a key Ex + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + ConSplitterTextInWaitForKey, + ConInPrivate, + &ConInPrivate->TextInEx.WaitForKeyEx + ); + ASSERT_EFI_ERROR (Status); + + InitializeListHead (&ConInPrivate->NotifyList); + + ConInPrivate->AbsolutePointer.Mode = &ConInPrivate->AbsolutePointerMode; + // + // Allocate buffer for Absolute Pointer device + // + Status = ConSplitterGrowBuffer ( + sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL *), + &ConInPrivate->AbsolutePointerListCount, + (VOID **) &ConInPrivate->AbsolutePointerList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Create Event to wait for device input for Absolute pointer device + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + ConSplitterAbsolutePointerWaitForInput, + ConInPrivate, + &ConInPrivate->AbsolutePointer.WaitForInput + ); + ASSERT_EFI_ERROR (Status); + + ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode; + // + // Allocate buffer for Simple Pointer device + // + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_POINTER_PROTOCOL *), + &ConInPrivate->PointerListCount, + (VOID **) &ConInPrivate->PointerList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Create Event to wait for device input for Simple pointer device + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + ConSplitterSimplePointerWaitForInput, + ConInPrivate, + &ConInPrivate->SimplePointer.WaitForInput + ); + ASSERT_EFI_ERROR (Status); + // + // Create Event to signal ConIn connection request + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + ConSplitterEmptyCallbackFunction, + NULL, + &gConnectConInEventGuid, + &ConInPrivate->ConnectConInEvent + ); + + return Status; +} + +/** + Construct console output devices' private data. + + @param ConOutPrivate A pointer to the TEXT_OUT_SPLITTER_PRIVATE_DATA + structure. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS Text Input Devcie's private data has been constructed. + +**/ +EFI_STATUS +ConSplitterTextOutConstructor ( + TEXT_OUT_SPLITTER_PRIVATE_DATA *ConOutPrivate + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + + // + // Copy protocols template + // + if (FeaturePcdGet (PcdConOutUgaSupport)) { + CopyMem (&ConOutPrivate->UgaDraw, &mUgaDrawProtocolTemplate, sizeof (EFI_UGA_DRAW_PROTOCOL)); + } + if (FeaturePcdGet (PcdConOutGopSupport)) { + CopyMem (&ConOutPrivate->GraphicsOutput, &mGraphicsOutputProtocolTemplate, sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL)); + } + + // + // Initilize console output splitter's private data. + // + ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode; + + // + // When new console device is added, the new mode will be set later, + // so put current mode back to init state. + // + ConOutPrivate->TextOutMode.Mode = 0xFF; + // + // Allocate buffer for Console Out device + // + Status = ConSplitterGrowBuffer ( + sizeof (TEXT_OUT_AND_GOP_DATA), + &ConOutPrivate->TextOutListCount, + (VOID **) &ConOutPrivate->TextOutList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Allocate buffer for Text Out query data + // + Status = ConSplitterGrowBuffer ( + sizeof (TEXT_OUT_SPLITTER_QUERY_DATA), + &ConOutPrivate->TextOutQueryDataCount, + (VOID **) &ConOutPrivate->TextOutQueryData + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Setup the default console to 80 x 25 and mode to 0 + // + ConOutPrivate->TextOutQueryData[0].Columns = 80; + ConOutPrivate->TextOutQueryData[0].Rows = 25; + TextOutSetMode (ConOutPrivate, 0); + + + if (FeaturePcdGet (PcdConOutUgaSupport)) { + // + // Setup the UgaDraw to 800 x 600 x 32 bits per pixel, 60Hz. + // + ConSplitterUgaDrawSetMode (&ConOutPrivate->UgaDraw, 800, 600, 32, 60); + } + if (FeaturePcdGet (PcdConOutGopSupport)) { + // + // Setup resource for mode information in Graphics Output Protocol interface + // + if ((ConOutPrivate->GraphicsOutput.Mode = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE))) == NULL) { + return EFI_OUT_OF_RESOURCES; + } + if ((ConOutPrivate->GraphicsOutput.Mode->Info = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Setup the DevNullGraphicsOutput to 800 x 600 x 32 bits per pixel + // DevNull will be updated to user-defined mode after driver has started. + // + if ((ConOutPrivate->GraphicsOutputModeBuffer = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))) == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Info = &ConOutPrivate->GraphicsOutputModeBuffer[0]; + Info->Version = 0; + Info->HorizontalResolution = 800; + Info->VerticalResolution = 600; + Info->PixelFormat = PixelBltOnly; + Info->PixelsPerScanLine = 800; + CopyMem (ConOutPrivate->GraphicsOutput.Mode->Info, Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); + ConOutPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + + // + // Initialize the following items, theset items remain unchanged in GraphicsOutput->SetMode() + // GraphicsOutputMode->FrameBufferBase, GraphicsOutputMode->FrameBufferSize + // + ConOutPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL; + ConOutPrivate->GraphicsOutput.Mode->FrameBufferSize = 0; + + ConOutPrivate->GraphicsOutput.Mode->MaxMode = 1; + // + // Initial current mode to unknown state, and then set to mode 0 + // + ConOutPrivate->GraphicsOutput.Mode->Mode = 0xffff; + ConOutPrivate->GraphicsOutput.SetMode (&ConOutPrivate->GraphicsOutput, 0); + } + + return EFI_SUCCESS; +} + + +/** + Test to see if the specified protocol could be supported on the specified device. + + @param This Driver Binding protocol pointer. + @param ControllerHandle Handle of device to test. + @param Guid The specified protocol. + + @retval EFI_SUCCESS The specified protocol is supported on this device. + @retval EFI_UNSUPPORTED The specified protocol attempts to be installed on virtul handle. + @retval other Failed to open specified protocol on this device. + +**/ +EFI_STATUS +ConSplitterSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_GUID *Guid + ) +{ + EFI_STATUS Status; + VOID *Instance; + + // + // Make sure the Console Splitter does not attempt to attach to itself + // + if (ControllerHandle == mConIn.VirtualHandle || + ControllerHandle == mConOut.VirtualHandle || + ControllerHandle == mStdErr.VirtualHandle + ) { + return EFI_UNSUPPORTED; + } + + // + // Check to see whether the specific protocol could be opened BY_DRIVER + // + Status = gBS->OpenProtocol ( + ControllerHandle, + Guid, + &Instance, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + ControllerHandle, + Guid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; +} + +/** + Test to see if Console In Device could be supported on the Controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiConsoleInDeviceGuid + ); +} + +/** + Test to see if Simple Pointer protocol could be supported on the Controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiSimplePointerProtocolGuid + ); +} + +/** + Test to see if Absolute Pointer protocol could be supported on the Controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterAbsolutePointerDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiAbsolutePointerProtocolGuid + ); +} + + +/** + Test to see if Console Out Device could be supported on the Controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiConsoleOutDeviceGuid + ); +} + +/** + Test to see if Standard Error Device could be supported on the Controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiStandardErrorDeviceGuid + ); +} + + +/** + Start ConSplitter on devcie handle by opening Console Device Guid on device handle + and the console virtual handle. And Get the console interface on controller handle. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device. + @param ConSplitterVirtualHandle Console virtual Handle. + @param DeviceGuid The specified Console Device, such as ConInDev, + ConOutDev. + @param InterfaceGuid The specified protocol to be opened. + @param Interface Protocol interface returned. + + @retval EFI_SUCCESS This driver supports this device. + @retval other Failed to open the specified Console Device Guid + or specified protocol. + +**/ +EFI_STATUS +ConSplitterStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ConSplitterVirtualHandle, + IN EFI_GUID *DeviceGuid, + IN EFI_GUID *InterfaceGuid, + OUT VOID **Interface + ) +{ + EFI_STATUS Status; + VOID *Instance; + + // + // Check to see whether the ControllerHandle has the DeviceGuid on it. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + DeviceGuid, + &Instance, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Open the Parent Handle for the child. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + DeviceGuid, + &Instance, + This->DriverBindingHandle, + ConSplitterVirtualHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + goto Err; + } + + // + // Open InterfaceGuid on the virtul handle. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + InterfaceGuid, + Interface, + This->DriverBindingHandle, + ConSplitterVirtualHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + // + // close the DeviceGuid on ConSplitter VirtualHandle. + // + gBS->CloseProtocol ( + ControllerHandle, + DeviceGuid, + This->DriverBindingHandle, + ConSplitterVirtualHandle + ); + +Err: + // + // close the DeviceGuid on ControllerHandle. + // + gBS->CloseProtocol ( + ControllerHandle, + DeviceGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return Status; +} + + +/** + Start Console In Consplitter on device handle. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS Console In Consplitter is added to ControllerHandle. + @retval other Console In Consplitter does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx; + + // + // Start ConSplitter on ControllerHandle, and create the virtual + // agrogated console device on first call Start for a SimpleTextIn handle. + // + Status = ConSplitterStart ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiConsoleInDeviceGuid, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &TextIn + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Add this device into Text In devices list. + // + Status = ConSplitterTextInAddDevice (&mConIn, TextIn); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextInputExProtocolGuid, + (VOID **) &TextInEx, + This->DriverBindingHandle, + mConIn.VirtualHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + // + // If Simple Text Input Ex protocol exists, + // add this device into Text In Ex devices list. + // + Status = ConSplitterTextInExAddDevice (&mConIn, TextInEx); + } + + return Status; +} + + +/** + Start Simple Pointer Consplitter on device handle. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS Simple Pointer Consplitter is added to ControllerHandle. + @retval other Simple Pointer Consplitter does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer; + + // + // Start ConSplitter on ControllerHandle, and create the virtual + // agrogated console device on first call Start for a SimplePointer handle. + // + Status = ConSplitterStart ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiSimplePointerProtocolGuid, + &gEfiSimplePointerProtocolGuid, + (VOID **) &SimplePointer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Add this devcie into Simple Pointer devices list. + // + return ConSplitterSimplePointerAddDevice (&mConIn, SimplePointer); +} + + +/** + Start Absolute Pointer Consplitter on device handle. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS Absolute Pointer Consplitter is added to ControllerHandle. + @retval other Absolute Pointer Consplitter does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterAbsolutePointerDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer; + + // + // Start ConSplitter on ControllerHandle, and create the virtual + // agrogated console device on first call Start for a AbsolutePointer handle. + // + Status = ConSplitterStart ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiAbsolutePointerProtocolGuid, + &gEfiAbsolutePointerProtocolGuid, + (VOID **) &AbsolutePointer + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Add this devcie into Absolute Pointer devices list. + // + return ConSplitterAbsolutePointerAddDevice (&mConIn, AbsolutePointer); +} + + +/** + Start Console Out Consplitter on device handle. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS Console Out Consplitter is added to ControllerHandle. + @retval other Console Out Consplitter does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + + // + // Start ConSplitter on ControllerHandle, and create the virtual + // agrogated console device on first call Start for a ConsoleOut handle. + // + Status = ConSplitterStart ( + This, + ControllerHandle, + mConOut.VirtualHandle, + &gEfiConsoleOutDeviceGuid, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + + GraphicsOutput = NULL; + UgaDraw = NULL; + // + // Try to Open Graphics Output protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &GraphicsOutput, + This->DriverBindingHandle, + mConOut.VirtualHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) { + // + // Open UGA DRAW protocol + // + gBS->OpenProtocol ( + ControllerHandle, + &gEfiUgaDrawProtocolGuid, + (VOID **) &UgaDraw, + This->DriverBindingHandle, + mConOut.VirtualHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + } + + // + // When new console device is added, the new mode will be set later, + // so put current mode back to init state. + // + mConOut.TextOutMode.Mode = 0xFF; + + // + // If both ConOut and StdErr incorporate the same Text Out device, + // their MaxMode and QueryData should be the intersection of both. + // + Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput, UgaDraw); + ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + + if (FeaturePcdGet (PcdConOutUgaSupport)) { + // + // Get the UGA mode data of ConOut from the current mode + // + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->QueryMode (GraphicsOutput, GraphicsOutput->Mode->Mode, &SizeOfInfo, &Info); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT ( SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); + + mConOut.UgaHorizontalResolution = Info->HorizontalResolution; + mConOut.UgaVerticalResolution = Info->VerticalResolution; + mConOut.UgaColorDepth = 32; + mConOut.UgaRefreshRate = 60; + + FreePool (Info); + + } else if (UgaDraw != NULL) { + Status = UgaDraw->GetMode ( + UgaDraw, + &mConOut.UgaHorizontalResolution, + &mConOut.UgaVerticalResolution, + &mConOut.UgaColorDepth, + &mConOut.UgaRefreshRate + ); + } + } + + return Status; +} + + +/** + Start Standard Error Consplitter on device handle. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS Standard Error Consplitter is added to ControllerHandle. + @retval other Standard Error Consplitter does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + + // + // Start ConSplitter on ControllerHandle, and create the virtual + // agrogated console device on first call Start for a StandardError handle. + // + Status = ConSplitterStart ( + This, + ControllerHandle, + mStdErr.VirtualHandle, + &gEfiStandardErrorDeviceGuid, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // When new console device is added, the new mode will be set later, + // so put current mode back to init state. + // + mStdErr.TextOutMode.Mode = 0xFF; + + // + // If both ConOut and StdErr incorporate the same Text Out device, + // their MaxMode and QueryData should be the intersection of both. + // + Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL); + ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + if (EFI_ERROR (Status)) { + return Status; + } + + return Status; +} + + +/** + Stop ConSplitter on device handle by closing Console Device Guid on device handle + and the console virtual handle. + + @param This Protocol instance pointer. + @param ControllerHandle Handle of device. + @param ConSplitterVirtualHandle Console virtual Handle. + @param DeviceGuid The specified Console Device, such as ConInDev, + ConOutDev. + @param InterfaceGuid The specified protocol to be opened. + @param Interface Protocol interface returned. + + @retval EFI_SUCCESS Stop ConSplitter on ControllerHandle successfully. + @retval other Failed to Stop ConSplitter on ControllerHandle. + +**/ +EFI_STATUS +ConSplitterStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ConSplitterVirtualHandle, + IN EFI_GUID *DeviceGuid, + IN EFI_GUID *InterfaceGuid, + IN VOID **Interface + ) +{ + EFI_STATUS Status; + + Status = gBS->OpenProtocol ( + ControllerHandle, + InterfaceGuid, + Interface, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // close the protocol refered. + // + gBS->CloseProtocol ( + ControllerHandle, + DeviceGuid, + This->DriverBindingHandle, + ConSplitterVirtualHandle + ); + + gBS->CloseProtocol ( + ControllerHandle, + DeviceGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; +} + + +/** + Stop Console In ConSplitter on ControllerHandle by closing Console In Devcice GUID. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextInputExProtocolGuid, + (VOID **) &TextInEx, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + // + // If Simple Text Input Ex protocol exists, + // remove device from Text Input Ex devices list. + // + Status = ConSplitterTextInExDeleteDevice (&mConIn, TextInEx); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Close Simple Text In protocol on controller handle and virtual handle. + // + Status = ConSplitterStop ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiConsoleInDeviceGuid, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &TextIn + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Remove device from Text Input devices list. + // + return ConSplitterTextInDeleteDevice (&mConIn, TextIn); +} + + +/** + Stop Simple Pointer protocol ConSplitter on ControllerHandle by closing + Simple Pointer protocol. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + // + // Close Simple Pointer protocol on controller handle and virtual handle. + // + Status = ConSplitterStop ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiSimplePointerProtocolGuid, + &gEfiSimplePointerProtocolGuid, + (VOID **) &SimplePointer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Remove this device from Simple Pointer device list. + // + return ConSplitterSimplePointerDeleteDevice (&mConIn, SimplePointer); +} + + +/** + Stop Absolute Pointer protocol ConSplitter on ControllerHandle by closing + Absolute Pointer protocol. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +ConSplitterAbsolutePointerDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + // + // Close Absolute Pointer protocol on controller handle and virtual handle. + // + Status = ConSplitterStop ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiAbsolutePointerProtocolGuid, + &gEfiAbsolutePointerProtocolGuid, + (VOID **) &AbsolutePointer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Remove this device from Absolute Pointer device list. + // + return ConSplitterAbsolutePointerDeleteDevice (&mConIn, AbsolutePointer); +} + + +/** + Stop Console Out ConSplitter on device handle by closing Console Out Devcice GUID. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + // + // Close Absolute Pointer protocol on controller handle and virtual handle. + // + Status = ConSplitterStop ( + This, + ControllerHandle, + mConOut.VirtualHandle, + &gEfiConsoleOutDeviceGuid, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Remove this device from Text Out device list. + // + return ConSplitterTextOutDeleteDevice (&mConOut, TextOut); +} + + +/** + Stop Standard Error ConSplitter on ControllerHandle by closing Standard Error GUID. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + // + // Close Standard Error Device on controller handle and virtual handle. + // + Status = ConSplitterStop ( + This, + ControllerHandle, + mStdErr.VirtualHandle, + &gEfiStandardErrorDeviceGuid, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Delete this console error out device's data structures. + // + return ConSplitterTextOutDeleteDevice (&mStdErr, TextOut); +} + + +/** + Take the passed in Buffer of size ElementSize and grow the buffer + by CONSOLE_SPLITTER_ALLOC_UNIT * ElementSize bytes. + Copy the current data in Buffer to the new version of Buffer and + free the old version of buffer. + + @param ElementSize Size of element in array. + @param Count Current number of elements in array. + @param Buffer Bigger version of passed in Buffer with all the + data. + + @retval EFI_SUCCESS Buffer size has grown. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterGrowBuffer ( + IN UINTN ElementSize, + IN OUT UINTN *Count, + IN OUT VOID **Buffer + ) +{ + VOID *Ptr; + + // + // grow the buffer to new buffer size, + // copy the old buffer's content to the new-size buffer, + // then free the old buffer. + // + Ptr = ReallocatePool ( + ElementSize * (*Count), + ElementSize * ((*Count) + CONSOLE_SPLITTER_ALLOC_UNIT), + *Buffer + ); + if (Ptr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + *Count += CONSOLE_SPLITTER_ALLOC_UNIT; + *Buffer = Ptr; + return EFI_SUCCESS; +} + + +/** + Add Text Input Device in Consplitter Text Input list. + + @param Private Text In Splitter pointer. + @param TextIn Simple Text Input protocol pointer. + + @retval EFI_SUCCESS Text Input Device added successfully. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterTextInAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn + ) +{ + EFI_STATUS Status; + + // + // If the Text In List is full, enlarge it by calling ConSplitterGrowBuffer(). + // + if (Private->CurrentNumberOfConsoles >= Private->TextInListCount) { + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *), + &Private->TextInListCount, + (VOID **) &Private->TextInList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + // + // Add the new text-in device data structure into the Text In List. + // + Private->TextInList[Private->CurrentNumberOfConsoles] = TextIn; + Private->CurrentNumberOfConsoles++; + + // + // Extra CheckEvent added to reduce the double CheckEvent(). + // + gBS->CheckEvent (TextIn->WaitForKey); + + return EFI_SUCCESS; +} + + +/** + Remove Text Input Device from Consplitter Text Input list. + + @param Private Text In Splitter pointer. + @param TextIn Simple Text protocol pointer. + + @retval EFI_SUCCESS Simple Text Device removed successfully. + @retval EFI_NOT_FOUND No Simple Text Device found. + +**/ +EFI_STATUS +ConSplitterTextInDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn + ) +{ + UINTN Index; + // + // Remove the specified text-in device data structure from the Text In List, + // and rearrange the remaining data structures in the Text In List. + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + if (Private->TextInList[Index] == TextIn) { + for (; Index < Private->CurrentNumberOfConsoles - 1; Index++) { + Private->TextInList[Index] = Private->TextInList[Index + 1]; + } + + Private->CurrentNumberOfConsoles--; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Add Text Input Ex Device in Consplitter Text Input Ex list. + + @param Private Text In Splitter pointer. + @param TextInEx Simple Text Input Ex Input protocol pointer. + + @retval EFI_SUCCESS Text Input Ex Device added successfully. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterTextInExAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify; + UINTN TextInExListCount; + + // + // Enlarge the NotifyHandleList and the TextInExList + // + if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) { + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link); + TextInExListCount = Private->TextInExListCount; + + Status = ConSplitterGrowBuffer ( + sizeof (EFI_HANDLE), + &TextInExListCount, + (VOID **) &CurrentNotify->NotifyHandleList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *), + &Private->TextInExListCount, + (VOID **) &Private->TextInExList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + + // + // Register the key notify in the new text-in device + // + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link); + Status = TextInEx->RegisterKeyNotify ( + TextInEx, + &CurrentNotify->KeyData, + CurrentNotify->KeyNotificationFn, + &CurrentNotify->NotifyHandleList[Private->CurrentNumberOfExConsoles] + ); + if (EFI_ERROR (Status)) { + for (Link = Link->BackLink; Link != &Private->NotifyList; Link = Link->BackLink) { + CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link); + TextInEx->UnregisterKeyNotify ( + TextInEx, + CurrentNotify->NotifyHandleList[Private->CurrentNumberOfExConsoles] + ); + } + return Status; + } + } + + // + // Add the new text-in device data structure into the Text Input Ex List. + // + Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx; + Private->CurrentNumberOfExConsoles++; + + // + // Extra CheckEvent added to reduce the double CheckEvent(). + // + gBS->CheckEvent (TextInEx->WaitForKeyEx); + + return EFI_SUCCESS; +} + +/** + Remove Text Ex Device from Consplitter Text Input Ex list. + + @param Private Text In Splitter pointer. + @param TextInEx Simple Text Ex protocol pointer. + + @retval EFI_SUCCESS Simple Text Input Ex Device removed successfully. + @retval EFI_NOT_FOUND No Simple Text Input Ex Device found. + +**/ +EFI_STATUS +ConSplitterTextInExDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx + ) +{ + UINTN Index; + // + // Remove the specified text-in device data structure from the Text Input Ex List, + // and rearrange the remaining data structures in the Text In List. + // + for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) { + if (Private->TextInExList[Index] == TextInEx) { + for (; Index < Private->CurrentNumberOfExConsoles - 1; Index++) { + Private->TextInExList[Index] = Private->TextInExList[Index + 1]; + } + + Private->CurrentNumberOfExConsoles--; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +/** + Add Simple Pointer Device in Consplitter Simple Pointer list. + + @param Private Text In Splitter pointer. + @param SimplePointer Simple Pointer protocol pointer. + + @retval EFI_SUCCESS Simple Pointer Device added successfully. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterSimplePointerAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer + ) +{ + EFI_STATUS Status; + + // + // If the Simple Pointer List is full, enlarge it by calling ConSplitterGrowBuffer(). + // + if (Private->CurrentNumberOfPointers >= Private->PointerListCount) { + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_POINTER_PROTOCOL *), + &Private->PointerListCount, + (VOID **) &Private->PointerList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + // + // Add the new text-in device data structure into the Simple Pointer List. + // + Private->PointerList[Private->CurrentNumberOfPointers] = SimplePointer; + Private->CurrentNumberOfPointers++; + + return EFI_SUCCESS; +} + + +/** + Remove Simple Pointer Device from Consplitter Simple Pointer list. + + @param Private Text In Splitter pointer. + @param SimplePointer Simple Pointer protocol pointer. + + @retval EFI_SUCCESS Simple Pointer Device removed successfully. + @retval EFI_NOT_FOUND No Simple Pointer Device found. + +**/ +EFI_STATUS +ConSplitterSimplePointerDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer + ) +{ + UINTN Index; + // + // Remove the specified text-in device data structure from the Simple Pointer List, + // and rearrange the remaining data structures in the Text In List. + // + for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) { + if (Private->PointerList[Index] == SimplePointer) { + for (; Index < Private->CurrentNumberOfPointers - 1; Index++) { + Private->PointerList[Index] = Private->PointerList[Index + 1]; + } + + Private->CurrentNumberOfPointers--; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +/** + Add Absolute Pointer Device in Consplitter Absolute Pointer list. + + @param Private Text In Splitter pointer. + @param AbsolutePointer Absolute Pointer protocol pointer. + + @retval EFI_SUCCESS Absolute Pointer Device added successfully. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterAbsolutePointerAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer + ) +{ + EFI_STATUS Status; + + // + // If the Absolute Pointer List is full, enlarge it by calling ConSplitterGrowBuffer(). + // + if (Private->CurrentNumberOfAbsolutePointers >= Private->AbsolutePointerListCount) { + Status = ConSplitterGrowBuffer ( + sizeof (EFI_ABSOLUTE_POINTER_PROTOCOL *), + &Private->AbsolutePointerListCount, + (VOID **) &Private->AbsolutePointerList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + // + // Add the new text-in device data structure into the Absolute Pointer List. + // + Private->AbsolutePointerList[Private->CurrentNumberOfAbsolutePointers] = AbsolutePointer; + Private->CurrentNumberOfAbsolutePointers++; + + return EFI_SUCCESS; +} + + +/** + Remove Absolute Pointer Device from Consplitter Absolute Pointer list. + + @param Private Text In Splitter pointer. + @param AbsolutePointer Absolute Pointer protocol pointer. + + @retval EFI_SUCCESS Absolute Pointer Device removed successfully. + @retval EFI_NOT_FOUND No Absolute Pointer Device found. + +**/ +EFI_STATUS +ConSplitterAbsolutePointerDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer + ) +{ + UINTN Index; + // + // Remove the specified text-in device data structure from the Absolute Pointer List, + // and rearrange the remaining data structures from the Absolute Pointer List. + // + for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) { + if (Private->AbsolutePointerList[Index] == AbsolutePointer) { + for (; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) { + Private->AbsolutePointerList[Index] = Private->AbsolutePointerList[Index + 1]; + } + + Private->CurrentNumberOfAbsolutePointers--; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Reallocate Text Out mode map. + + Allocate new buffer and copy original buffer into the new buffer. + + @param Private Consplitter Text Out pointer. + + @retval EFI_SUCCESS Buffer size has grown + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterGrowMapTable ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +{ + UINTN Size; + UINTN NewSize; + UINTN TotalSize; + INT32 *TextOutModeMap; + INT32 *OldTextOutModeMap; + INT32 *SrcAddress; + INT32 Index; + UINTN OldStepSize; + UINTN NewStepSize; + + NewSize = Private->TextOutListCount * sizeof (INT32); + OldTextOutModeMap = Private->TextOutModeMap; + TotalSize = NewSize * (Private->TextOutQueryDataCount); + + // + // Allocate new buffer for Text Out List. + // + TextOutModeMap = AllocatePool (TotalSize); + if (TextOutModeMap == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (TextOutModeMap, TotalSize, 0xFF); + Private->TextOutModeMap = TextOutModeMap; + + // + // If TextOutList has been enlarged, need to realloc the mode map table + // The mode map table is regarded as a two dimension array. + // + // Old New + // 0 ---------> TextOutListCount ----> TextOutListCount + // | ------------------------------------------- + // | | | | + // | | | | + // | | | | + // | | | | + // | | | | + // \/ | | | + // ------------------------------------------- + // QueryDataCount + // + if (OldTextOutModeMap != NULL) { + + Size = Private->CurrentNumberOfConsoles * sizeof (INT32); + Index = 0; + SrcAddress = OldTextOutModeMap; + NewStepSize = NewSize / sizeof(INT32); + // If Private->CurrentNumberOfConsoles is not zero and OldTextOutModeMap + // is not NULL, it indicates that the original TextOutModeMap is not enough + // for the new console devices and has been enlarged by CONSOLE_SPLITTER_ALLOC_UNIT columns. + // + OldStepSize = NewStepSize - CONSOLE_SPLITTER_ALLOC_UNIT; + + // + // Copy the old data to the new one + // + while (Index < Private->TextOutMode.MaxMode) { + CopyMem (TextOutModeMap, SrcAddress, Size); + // + // Go to next row of new TextOutModeMap. + // + TextOutModeMap += NewStepSize; + // + // Go to next row of old TextOutModeMap. + // + SrcAddress += OldStepSize; + Index++; + } + // + // Free the old buffer + // + FreePool (OldTextOutModeMap); + } + + return EFI_SUCCESS; +} + + +/** + Add new device's output mode to console splitter's mode list. + + @param Private Text Out Splitter pointer + @param TextOut Simple Text Output protocol pointer. + + @retval EFI_SUCCESS Device added successfully. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterAddOutputMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut + ) +{ + EFI_STATUS Status; + INT32 MaxMode; + INT32 Mode; + UINTN Index; + + MaxMode = TextOut->Mode->MaxMode; + Private->TextOutMode.MaxMode = MaxMode; + + // + // Grow the buffer if query data buffer is not large enough to + // hold all the mode supported by the first console. + // + while (MaxMode > (INT32) Private->TextOutQueryDataCount) { + Status = ConSplitterGrowBuffer ( + sizeof (TEXT_OUT_SPLITTER_QUERY_DATA), + &Private->TextOutQueryDataCount, + (VOID **) &Private->TextOutQueryData + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + // + // Allocate buffer for the output mode map + // + Status = ConSplitterGrowMapTable (Private); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // As the first textout device, directly add the mode in to QueryData + // and at the same time record the mapping between QueryData and TextOut. + // + Mode = 0; + Index = 0; + while (Mode < MaxMode) { + Status = TextOut->QueryMode ( + TextOut, + Mode, + &Private->TextOutQueryData[Mode].Columns, + &Private->TextOutQueryData[Mode].Rows + ); + // + // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData + // is clear to 0x0. + // + if ((EFI_ERROR(Status)) && (Mode == 1)) { + Private->TextOutQueryData[Mode].Columns = 0; + Private->TextOutQueryData[Mode].Rows = 0; + } + Private->TextOutModeMap[Index] = Mode; + Mode++; + Index += Private->TextOutListCount; + } + + return EFI_SUCCESS; +} + +/** + Reconstruct TextOutModeMap to get intersection of modes. + + This routine reconstruct TextOutModeMap to get the intersection + of modes for all console out devices. Because EFI/UEFI spec require + mode 0 is 80x25, mode 1 is 80x50, this routine will not check the + intersection for mode 0 and mode 1. + + @param TextOutModeMap Current text out mode map, begin with the mode 80x25 + @param NewlyAddedMap New text out mode map, begin with the mode 80x25 + @param MapStepSize Mode step size for one console device + @param NewMapStepSize New Mode step size for one console device + @param MaxMode IN: Current max text mode, OUT: Updated max text mode. + @param CurrentMode IN: Current text mode, OUT: Updated current text mode. + +**/ +VOID +ConSplitterGetIntersection ( + IN INT32 *TextOutModeMap, + IN INT32 *NewlyAddedMap, + IN UINTN MapStepSize, + IN UINTN NewMapStepSize, + IN OUT INT32 *MaxMode, + IN OUT INT32 *CurrentMode + ) +{ + INT32 Index; + INT32 *CurrentMapEntry; + INT32 *NextMapEntry; + INT32 *NewMapEntry; + INT32 CurrentMaxMode; + INT32 Mode; + + // + // According to EFI/UEFI spec, mode 0 and mode 1 have been reserved + // for 80x25 and 80x50 in Simple Text Out protocol, so don't make intersection + // for mode 0 and mode 1, mode number starts from 2. + // + Index = 2; + CurrentMapEntry = &TextOutModeMap[MapStepSize * 2]; + NextMapEntry = CurrentMapEntry; + NewMapEntry = &NewlyAddedMap[NewMapStepSize * 2]; + + CurrentMaxMode = *MaxMode; + Mode = *CurrentMode; + + while (Index < CurrentMaxMode) { + if (*NewMapEntry == -1) { + // + // This mode is not supported any more. Remove it. Special care + // must be taken as this remove will also affect current mode; + // + if (Index == *CurrentMode) { + Mode = -1; + } else if (Index < *CurrentMode) { + Mode--; + } + (*MaxMode)--; + } else { + if (CurrentMapEntry != NextMapEntry) { + CopyMem (NextMapEntry, CurrentMapEntry, MapStepSize * sizeof (INT32)); + } + + NextMapEntry += MapStepSize; + } + + CurrentMapEntry += MapStepSize; + NewMapEntry += NewMapStepSize; + Index++; + } + + *CurrentMode = Mode; + + return ; +} + +/** + Sync the device's output mode to console splitter's mode list. + + @param Private Text Out Splitter pointer. + @param TextOut Simple Text Output protocol pointer. + +**/ +VOID +ConSplitterSyncOutputMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut + ) +{ + INT32 CurrentMaxMode; + INT32 Mode; + INT32 Index; + INT32 *TextOutModeMap; + INT32 *MapTable; + INT32 QueryMode; + TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData; + UINTN Rows; + UINTN Columns; + UINTN StepSize; + EFI_STATUS Status; + + // + // Must make sure that current mode won't change even if mode number changes + // + CurrentMaxMode = Private->TextOutMode.MaxMode; + TextOutModeMap = Private->TextOutModeMap; + StepSize = Private->TextOutListCount; + TextOutQueryData = Private->TextOutQueryData; + + // + // Query all the mode that the newly added TextOut supports + // + Mode = 0; + MapTable = TextOutModeMap + Private->CurrentNumberOfConsoles; + while (Mode < TextOut->Mode->MaxMode) { + Status = TextOut->QueryMode (TextOut, Mode, &Columns, &Rows); + + if (EFI_ERROR(Status)) { + if (Mode == 1) { + // + // If mode 1 (80x50) is not supported, make sure mode 1 in TextOutQueryData + // is clear to 0x0. + // + MapTable[StepSize] = Mode; + TextOutQueryData[Mode].Columns = 0; + TextOutQueryData[Mode].Rows = 0; + } + Mode++; + continue; + } + // + // Search the intersection map and QueryData database to see if they intersects + // + Index = 0; + while (Index < CurrentMaxMode) { + QueryMode = *(TextOutModeMap + Index * StepSize); + if ((TextOutQueryData[QueryMode].Rows == Rows) && (TextOutQueryData[QueryMode].Columns == Columns)) { + MapTable[Index * StepSize] = Mode; + break; + } + Index++; + } + Mode++; + } + // + // Now search the TextOutModeMap table to find the intersection of supported + // mode between ConSplitter and the newly added device. + // + ConSplitterGetIntersection ( + TextOutModeMap, + MapTable, + StepSize, + StepSize, + &Private->TextOutMode.MaxMode, + &Private->TextOutMode.Mode + ); + + return ; +} + + +/** + Sync output device between ConOut and StdErr output. + + @retval EFI_SUCCESS Sync implemented successfully. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterGetIntersectionBetweenConOutAndStrErr ( + VOID + ) +{ + UINTN ConOutNumOfConsoles; + UINTN StdErrNumOfConsoles; + TEXT_OUT_AND_GOP_DATA *ConOutTextOutList; + TEXT_OUT_AND_GOP_DATA *StdErrTextOutList; + UINTN Indexi; + UINTN Indexj; + UINTN ConOutRows; + UINTN ConOutColumns; + UINTN StdErrRows; + UINTN StdErrColumns; + INT32 ConOutMaxMode; + INT32 StdErrMaxMode; + INT32 ConOutMode; + INT32 StdErrMode; + INT32 Mode; + INT32 Index; + INT32 *ConOutModeMap; + INT32 *StdErrModeMap; + INT32 *ConOutMapTable; + INT32 *StdErrMapTable; + TEXT_OUT_SPLITTER_QUERY_DATA *ConOutQueryData; + TEXT_OUT_SPLITTER_QUERY_DATA *StdErrQueryData; + UINTN ConOutStepSize; + UINTN StdErrStepSize; + BOOLEAN FoundTheSameTextOut; + UINTN ConOutMapTableSize; + UINTN StdErrMapTableSize; + + ConOutNumOfConsoles = mConOut.CurrentNumberOfConsoles; + StdErrNumOfConsoles = mStdErr.CurrentNumberOfConsoles; + ConOutTextOutList = mConOut.TextOutList; + StdErrTextOutList = mStdErr.TextOutList; + + Indexi = 0; + FoundTheSameTextOut = FALSE; + while ((Indexi < ConOutNumOfConsoles) && (!FoundTheSameTextOut)) { + Indexj = 0; + while (Indexj < StdErrNumOfConsoles) { + if (ConOutTextOutList->TextOut == StdErrTextOutList->TextOut) { + FoundTheSameTextOut = TRUE; + break; + } + + Indexj++; + StdErrTextOutList++; + } + + Indexi++; + ConOutTextOutList++; + } + + if (!FoundTheSameTextOut) { + return EFI_SUCCESS; + } + // + // Must make sure that current mode won't change even if mode number changes + // + ConOutMaxMode = mConOut.TextOutMode.MaxMode; + ConOutModeMap = mConOut.TextOutModeMap; + ConOutStepSize = mConOut.TextOutListCount; + ConOutQueryData = mConOut.TextOutQueryData; + + StdErrMaxMode = mStdErr.TextOutMode.MaxMode; + StdErrModeMap = mStdErr.TextOutModeMap; + StdErrStepSize = mStdErr.TextOutListCount; + StdErrQueryData = mStdErr.TextOutQueryData; + + // + // Allocate the map table and set the map table's index to -1. + // + ConOutMapTableSize = ConOutMaxMode * sizeof (INT32); + ConOutMapTable = AllocateZeroPool (ConOutMapTableSize); + if (ConOutMapTable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (ConOutMapTable, ConOutMapTableSize, 0xFF); + + StdErrMapTableSize = StdErrMaxMode * sizeof (INT32); + StdErrMapTable = AllocateZeroPool (StdErrMapTableSize); + if (StdErrMapTable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (StdErrMapTable, StdErrMapTableSize, 0xFF); + + // + // Find the intersection of the two set of modes. If they actually intersect, the + // correponding entry in the map table is set to 1. + // + Mode = 0; + while (Mode < ConOutMaxMode) { + // + // Search the intersection map and QueryData database to see if they intersect + // + Index = 0; + ConOutMode = *(ConOutModeMap + Mode * ConOutStepSize); + ConOutRows = ConOutQueryData[ConOutMode].Rows; + ConOutColumns = ConOutQueryData[ConOutMode].Columns; + while (Index < StdErrMaxMode) { + StdErrMode = *(StdErrModeMap + Index * StdErrStepSize); + StdErrRows = StdErrQueryData[StdErrMode].Rows; + StdErrColumns = StdErrQueryData[StdErrMode].Columns; + if ((StdErrRows == ConOutRows) && (StdErrColumns == ConOutColumns)) { + ConOutMapTable[Mode] = 1; + StdErrMapTable[Index] = 1; + break; + } + + Index++; + } + + Mode++; + } + // + // Now search the TextOutModeMap table to find the intersection of supported + // mode between ConSplitter and the newly added device. + // + ConSplitterGetIntersection ( + ConOutModeMap, + ConOutMapTable, + mConOut.TextOutListCount, + 1, + &(mConOut.TextOutMode.MaxMode), + &(mConOut.TextOutMode.Mode) + ); + + if (mConOut.TextOutMode.Mode < 0) { + mConOut.TextOut.SetMode (&(mConOut.TextOut), 0); + } + + ConSplitterGetIntersection ( + StdErrModeMap, + StdErrMapTable, + mStdErr.TextOutListCount, + 1, + &(mStdErr.TextOutMode.MaxMode), + &(mStdErr.TextOutMode.Mode) + ); + + if (mStdErr.TextOutMode.Mode < 0) { + mStdErr.TextOut.SetMode (&(mStdErr.TextOut), 0); + } + + FreePool (ConOutMapTable); + FreePool (StdErrMapTable); + + return EFI_SUCCESS; +} + + +/** + Add Grahpics Output modes into Consplitter Text Out list. + + @param Private Text Out Splitter pointer. + @param GraphicsOutput Graphics Output protocol pointer. + @param UgaDraw UGA Draw protocol pointer. + + @retval EFI_SUCCESS Output mode added successfully. + @retval other Failed to add output mode. + +**/ +EFI_STATUS +ConSplitterAddGraphicsOutputMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN CurrentIndex; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *CurrentGraphicsOutputMode; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeBuffer; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *MatchedMode; + UINTN NumberIndex; + BOOLEAN Match; + BOOLEAN AlreadyExist; + UINT32 UgaHorizontalResolution; + UINT32 UgaVerticalResolution; + UINT32 UgaColorDepth; + UINT32 UgaRefreshRate; + + ASSERT (GraphicsOutput != NULL || UgaDraw != NULL); + + CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode; + + Index = 0; + CurrentIndex = 0; + Status = EFI_SUCCESS; + + if (Private->CurrentNumberOfUgaDraw != 0) { + // + // If any UGA device has already been added, then there is no need to + // calculate intersection of display mode of different GOP/UGA device, + // since only one display mode will be exported (i.e. user-defined mode) + // + goto Done; + } + + if (GraphicsOutput != NULL) { + if (Private->CurrentNumberOfGraphicsOutput == 0) { + // + // This is the first Graphics Output device added + // + CurrentGraphicsOutputMode->MaxMode = GraphicsOutput->Mode->MaxMode; + CurrentGraphicsOutputMode->Mode = GraphicsOutput->Mode->Mode; + CopyMem (CurrentGraphicsOutputMode->Info, GraphicsOutput->Mode->Info, GraphicsOutput->Mode->SizeOfInfo); + CurrentGraphicsOutputMode->SizeOfInfo = GraphicsOutput->Mode->SizeOfInfo; + CurrentGraphicsOutputMode->FrameBufferBase = GraphicsOutput->Mode->FrameBufferBase; + CurrentGraphicsOutputMode->FrameBufferSize = GraphicsOutput->Mode->FrameBufferSize; + + // + // Allocate resource for the private mode buffer + // + ModeBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * GraphicsOutput->Mode->MaxMode); + if (ModeBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + FreePool (Private->GraphicsOutputModeBuffer); + Private->GraphicsOutputModeBuffer = ModeBuffer; + + // + // Store all supported display modes to the private mode buffer + // + Mode = ModeBuffer; + for (Index = 0; Index < GraphicsOutput->Mode->MaxMode; Index++) { + // + // The Info buffer would be allocated by callee + // + Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) Index, &SizeOfInfo, &Info); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT ( SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); + CopyMem (Mode, Info, SizeOfInfo); + Mode++; + FreePool (Info); + } + } else { + // + // Check intersection of display mode + // + ModeBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * CurrentGraphicsOutputMode->MaxMode); + if (ModeBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + MatchedMode = ModeBuffer; + Mode = &Private->GraphicsOutputModeBuffer[0]; + for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) { + Match = FALSE; + + for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex++) { + // + // The Info buffer would be allocated by callee + // + Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info); + if (EFI_ERROR (Status)) { + return Status; + } + if ((Info->HorizontalResolution == Mode->HorizontalResolution) && + (Info->VerticalResolution == Mode->VerticalResolution)) { + // + // If GOP device supports one mode in current mode buffer, + // it will be added into matched mode buffer + // + Match = TRUE; + FreePool (Info); + break; + } + FreePool (Info); + } + + if (Match) { + AlreadyExist = FALSE; + + // + // Check if GOP mode has been in the mode buffer, ModeBuffer = MatchedMode at begin. + // + for (Info = ModeBuffer; Info < MatchedMode; Info++) { + if ((Info->HorizontalResolution == Mode->HorizontalResolution) && + (Info->VerticalResolution == Mode->VerticalResolution)) { + AlreadyExist = TRUE; + break; + } + } + + if (!AlreadyExist) { + CopyMem (MatchedMode, Mode, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); + + // + // Physical frame buffer is no longer available, change PixelFormat to PixelBltOnly + // + MatchedMode->Version = 0; + MatchedMode->PixelFormat = PixelBltOnly; + ZeroMem (&MatchedMode->PixelInformation, sizeof (EFI_PIXEL_BITMASK)); + + MatchedMode++; + } + } + + Mode++; + } + + // + // Drop the old mode buffer, assign it to a new one + // + FreePool (Private->GraphicsOutputModeBuffer); + Private->GraphicsOutputModeBuffer = ModeBuffer; + + // + // Physical frame buffer is no longer available when there are more than one physical GOP devices + // + CurrentGraphicsOutputMode->MaxMode = (UINT32) (((UINTN) MatchedMode - (UINTN) ModeBuffer) / sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); + CurrentGraphicsOutputMode->Info->PixelFormat = PixelBltOnly; + ZeroMem (&CurrentGraphicsOutputMode->Info->PixelInformation, sizeof (EFI_PIXEL_BITMASK)); + CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL; + CurrentGraphicsOutputMode->FrameBufferSize = 0; + } + + // + // Graphics console driver can ensure the same mode for all GOP devices + // + for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) { + Mode = &Private->GraphicsOutputModeBuffer[Index]; + if ((Mode->HorizontalResolution == GraphicsOutput->Mode->Info->HorizontalResolution) && + (Mode->VerticalResolution == GraphicsOutput->Mode->Info->VerticalResolution)) { + CurrentIndex = Index; + break; + } + } + if (Index >= CurrentGraphicsOutputMode->MaxMode) { + // + // if user defined mode is not found, set to default mode 800x600 + // + for (Index = 0; Index < CurrentGraphicsOutputMode->MaxMode; Index++) { + Mode = &Private->GraphicsOutputModeBuffer[Index]; + if ((Mode->HorizontalResolution == 800) && (Mode->VerticalResolution == 600)) { + CurrentIndex = Index; + break; + } + } + } + } else if (UgaDraw != NULL) { + // + // Graphics console driver can ensure the same mode for all GOP devices + // so we can get the current mode from this video device + // + UgaDraw->GetMode ( + UgaDraw, + &UgaHorizontalResolution, + &UgaVerticalResolution, + &UgaColorDepth, + &UgaRefreshRate + ); + + CurrentGraphicsOutputMode->MaxMode = 1; + Info = CurrentGraphicsOutputMode->Info; + Info->Version = 0; + Info->HorizontalResolution = UgaHorizontalResolution; + Info->VerticalResolution = UgaVerticalResolution; + Info->PixelFormat = PixelBltOnly; + Info->PixelsPerScanLine = UgaHorizontalResolution; + CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL; + CurrentGraphicsOutputMode->FrameBufferSize = 0; + + // + // Update the private mode buffer + // + CopyMem (&Private->GraphicsOutputModeBuffer[0], Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); + + // + // Only mode 0 is available to be set + // + CurrentIndex = 0; + } + +Done: + + if (GraphicsOutput != NULL) { + Private->CurrentNumberOfGraphicsOutput++; + } + if (UgaDraw != NULL) { + Private->CurrentNumberOfUgaDraw++; + } + + // + // Force GraphicsOutput mode to be set, + // + + Mode = &Private->GraphicsOutputModeBuffer[CurrentIndex]; + if ((GraphicsOutput != NULL) && + (Mode->HorizontalResolution == CurrentGraphicsOutputMode->Info->HorizontalResolution) && + (Mode->VerticalResolution == CurrentGraphicsOutputMode->Info->VerticalResolution)) { + CurrentGraphicsOutputMode->Mode = (UINT32) CurrentIndex; + if ((Mode->HorizontalResolution != GraphicsOutput->Mode->Info->HorizontalResolution) || + (Mode->VerticalResolution != GraphicsOutput->Mode->Info->VerticalResolution)) { + // + // If all existing video device has been set to common mode, only set new GOP device to + // the common mode + // + for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) { + Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info); + if (EFI_ERROR (Status)) { + return Status; + } + if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) { + FreePool (Info); + break; + } + FreePool (Info); + } + Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex); + } + } else { + // + // Current mode number may need update now, so set it to an invalid mode number + // + CurrentGraphicsOutputMode->Mode = 0xffff; + // + // Graphics console can ensure all GOP devices have the same mode which can be taken as current mode. + // + Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, (UINT32) CurrentIndex); + if (EFI_ERROR(Status)) { + // + // If user defined mode is not valid for display device, set to the default mode 800x600. + // + (Private->GraphicsOutputModeBuffer[0]).HorizontalResolution = 800; + (Private->GraphicsOutputModeBuffer[0]).VerticalResolution = 600; + Status = Private->GraphicsOutput.SetMode (&Private->GraphicsOutput, 0); + } + } + + return Status; +} + +/** + Set the current console out mode. + + This routine will get the current console mode information (column, row) + from ConsoleOutMode variable and set it; if the variable does not exist, + set to user defined console mode. + + @param Private Consplitter Text Out pointer. + +**/ +VOID +ConsplitterSetConsoleOutMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +{ + UINTN Col; + UINTN Row; + UINTN Mode; + UINTN PreferMode; + UINTN BaseMode; + UINTN MaxMode; + EFI_STATUS Status; + CONSOLE_OUT_MODE ModeInfo; + CONSOLE_OUT_MODE MaxModeInfo; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + + PreferMode = 0xFF; + BaseMode = 0xFF; + TextOut = &Private->TextOut; + MaxMode = (UINTN) (TextOut->Mode->MaxMode); + + MaxModeInfo.Column = 0; + MaxModeInfo.Row = 0; + ModeInfo.Column = PcdGet32 (PcdConOutColumn); + ModeInfo.Row = PcdGet32 (PcdConOutRow); + + // + // To find the prefer mode and basic mode from Text Out mode list + // + for (Mode = 0; Mode < MaxMode; Mode++) { + Status = TextOut->QueryMode (TextOut, Mode, &Col, &Row); + if (!EFI_ERROR(Status)) { + if ((ModeInfo.Column != 0) && (ModeInfo.Row != 0)) { + // + // Use user defined column and row + // + if (Col == ModeInfo.Column && Row == ModeInfo.Row) { + PreferMode = Mode; + } + } else { + // + // If user sets PcdConOutColumn or PcdConOutRow to 0, + // find and set the highest text mode. + // + if ((Col >= MaxModeInfo.Column) && (Row >= MaxModeInfo.Row)) { + MaxModeInfo.Column = Col; + MaxModeInfo.Row = Row; + PreferMode = Mode; + } + } + if (Col == 80 && Row == 25) { + BaseMode = Mode; + } + } + } + + // + // Set prefer mode to Text Out devices. + // + Status = TextOut->SetMode (TextOut, PreferMode); + if (EFI_ERROR(Status)) { + // + // if current mode setting is failed, default 80x25 mode will be set. + // + Status = TextOut->SetMode (TextOut, BaseMode); + ASSERT(!EFI_ERROR(Status)); + + PcdSet32 (PcdConOutColumn, 80); + PcdSet32 (PcdConOutRow, 25); + } + + return ; +} + + +/** + Add Text Output Device in Consplitter Text Output list. + + @param Private Text Out Splitter pointer. + @param TextOut Simple Text Output protocol pointer. + @param GraphicsOutput Graphics Output protocol pointer. + @param UgaDraw UGA Draw protocol pointer. + + @retval EFI_SUCCESS Text Output Device added successfully. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterTextOutAddDevice ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut, + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw + ) +{ + EFI_STATUS Status; + UINTN CurrentNumOfConsoles; + INT32 MaxMode; + UINT32 UgaHorizontalResolution; + UINT32 UgaVerticalResolution; + UINT32 UgaColorDepth; + UINT32 UgaRefreshRate; + TEXT_OUT_AND_GOP_DATA *TextAndGop; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + EFI_STATUS DeviceStatus; + + Status = EFI_SUCCESS; + CurrentNumOfConsoles = Private->CurrentNumberOfConsoles; + + // + // If the Text Out List is full, enlarge it by calling ConSplitterGrowBuffer(). + // + while (CurrentNumOfConsoles >= Private->TextOutListCount) { + Status = ConSplitterGrowBuffer ( + sizeof (TEXT_OUT_AND_GOP_DATA), + &Private->TextOutListCount, + (VOID **) &Private->TextOutList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Also need to reallocate the TextOutModeMap table + // + Status = ConSplitterGrowMapTable (Private); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + + TextAndGop = &Private->TextOutList[CurrentNumOfConsoles]; + + TextAndGop->TextOut = TextOut; + TextAndGop->GraphicsOutput = GraphicsOutput; + TextAndGop->UgaDraw = UgaDraw; + + if (CurrentNumOfConsoles == 0) { + // + // Add the first device's output mode to console splitter's mode list + // + Status = ConSplitterAddOutputMode (Private, TextOut); + } else { + ConSplitterSyncOutputMode (Private, TextOut); + } + + Private->CurrentNumberOfConsoles++; + + // + // Scan both TextOutList, for the intersection TextOut device + // maybe both ConOut and StdErr incorporate the same Text Out + // device in them, thus the output of both should be synced. + // + ConSplitterGetIntersectionBetweenConOutAndStrErr (); + + MaxMode = Private->TextOutMode.MaxMode; + ASSERT (MaxMode >= 1); + + DeviceStatus = EFI_DEVICE_ERROR; + Status = EFI_DEVICE_ERROR; + + // + // This device display mode will be added into Graphics Ouput modes. + // + if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) { + DeviceStatus = ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw); + } + + if (FeaturePcdGet (PcdConOutUgaSupport)) { + // + // If UGA is produced by Consplitter + // + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->QueryMode (GraphicsOutput, GraphicsOutput->Mode->Mode, &SizeOfInfo, &Info); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT ( SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); + + UgaHorizontalResolution = Info->HorizontalResolution; + UgaVerticalResolution = Info->VerticalResolution; + + FreePool (Info); + + } else if (UgaDraw != NULL) { + Status = UgaDraw->GetMode ( + UgaDraw, + &UgaHorizontalResolution, + &UgaVerticalResolution, + &UgaColorDepth, + &UgaRefreshRate + ); + if (!EFI_ERROR (Status) && EFI_ERROR (DeviceStatus)) { + // + // if GetMode is successfully and UGA device hasn't been set, set it + // + Status = ConSplitterUgaDrawSetMode ( + &Private->UgaDraw, + UgaHorizontalResolution, + UgaVerticalResolution, + UgaColorDepth, + UgaRefreshRate + ); + } + // + // If GetMode/SetMode is failed, set to 800x600 mode + // + if(EFI_ERROR (Status)) { + Status = ConSplitterUgaDrawSetMode ( + &Private->UgaDraw, + 800, + 600, + 32, + 60 + ); + } + } + } + + if (((!EFI_ERROR (DeviceStatus)) || (!EFI_ERROR (Status))) && + ((Private->CurrentNumberOfGraphicsOutput + Private->CurrentNumberOfUgaDraw) == 1)) { + if (!FeaturePcdGet (PcdConOutGopSupport)) { + // + // If Graphics Outpurt protocol not supported, UGA Draw protocol is installed + // on the virtual handle. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mConOut.VirtualHandle, + &gEfiUgaDrawProtocolGuid, + &mConOut.UgaDraw, + NULL + ); + } else if (!FeaturePcdGet (PcdConOutUgaSupport)) { + // + // If UGA Draw protocol not supported, Graphics Output Protocol is installed + // on virtual handle. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mConOut.VirtualHandle, + &gEfiGraphicsOutputProtocolGuid, + &mConOut.GraphicsOutput, + NULL + ); + } else { + // + // Boot Graphics Output protocol and UGA Draw protocol are supported, + // both they will be installed on virtual handle. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mConOut.VirtualHandle, + &gEfiGraphicsOutputProtocolGuid, + &mConOut.GraphicsOutput, + &gEfiUgaDrawProtocolGuid, + &mConOut.UgaDraw, + NULL + ); + } + } + + // + // After adding new console device, all existing console devices should be + // synced to the current shared mode. + // + ConsplitterSetConsoleOutMode (Private); + + return Status; +} + + +/** + Remove Text Out Device in Consplitter Text Out list. + + @param Private Text Out Splitter pointer. + @param TextOut Simple Text Output Pointer protocol pointer. + + @retval EFI_SUCCESS Text Out Device removed successfully. + @retval EFI_NOT_FOUND No Text Out Device found. + +**/ +EFI_STATUS +ConSplitterTextOutDeleteDevice ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut + ) +{ + INT32 Index; + UINTN CurrentNumOfConsoles; + TEXT_OUT_AND_GOP_DATA *TextOutList; + EFI_STATUS Status; + + // + // Remove the specified text-out device data structure from the Text out List, + // and rearrange the remaining data structures in the Text out List. + // + CurrentNumOfConsoles = Private->CurrentNumberOfConsoles; + Index = (INT32) CurrentNumOfConsoles - 1; + TextOutList = Private->TextOutList; + while (Index >= 0) { + if (TextOutList->TextOut == TextOut) { + if (TextOutList->UgaDraw != NULL) { + Private->CurrentNumberOfUgaDraw--; + } + if (TextOutList->GraphicsOutput != NULL) { + Private->CurrentNumberOfGraphicsOutput--; + } + CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index); + CurrentNumOfConsoles--; + break; + } + + Index--; + TextOutList++; + } + // + // The specified TextOut is not managed by the ConSplitter driver + // + if (Index < 0) { + return EFI_NOT_FOUND; + } + + if ((Private->CurrentNumberOfGraphicsOutput == 0) && (Private->CurrentNumberOfUgaDraw == 0)) { + // + // If there is not any physical GOP and UGA device in system, + // Consplitter GOP or UGA protocol will be uninstalled + // + if (!FeaturePcdGet (PcdConOutGopSupport)) { + Status = gBS->UninstallProtocolInterface ( + Private->VirtualHandle, + &gEfiUgaDrawProtocolGuid, + &Private->UgaDraw + ); + } else if (!FeaturePcdGet (PcdConOutUgaSupport)) { + Status = gBS->UninstallProtocolInterface ( + Private->VirtualHandle, + &gEfiGraphicsOutputProtocolGuid, + &Private->GraphicsOutput + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + Private->VirtualHandle, + &gEfiUgaDrawProtocolGuid, + &Private->UgaDraw, + &gEfiGraphicsOutputProtocolGuid, + &Private->GraphicsOutput, + NULL + ); + } + } + + if (CurrentNumOfConsoles == 0) { + // + // If the number of consoles is zero, reset all parameters + // + Private->CurrentNumberOfConsoles = 0; + Private->TextOutMode.MaxMode = 1; + Private->TextOutQueryData[0].Columns = 80; + Private->TextOutQueryData[0].Rows = 25; + TextOutSetMode (Private, 0); + + return EFI_SUCCESS; + } + // + // Max Mode is realy an intersection of the QueryMode command to all + // devices. So we must copy the QueryMode of the first device to + // QueryData. + // + ZeroMem ( + Private->TextOutQueryData, + Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA) + ); + + FreePool (Private->TextOutModeMap); + Private->TextOutModeMap = NULL; + TextOutList = Private->TextOutList; + + // + // Add the first TextOut to the QueryData array and ModeMap table + // + Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut); + + // + // Now add one by one + // + Index = 1; + Private->CurrentNumberOfConsoles = 1; + TextOutList++; + while ((UINTN) Index < CurrentNumOfConsoles) { + ConSplitterSyncOutputMode (Private, TextOutList->TextOut); + Index++; + Private->CurrentNumberOfConsoles++; + TextOutList++; + } + + ConSplitterGetIntersectionBetweenConOutAndStrErr (); + + return Status; +} + + +/** + Reset the input device and optionaly run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + Private->KeyEventSignalState = FALSE; + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextInList[Index]->Reset ( + Private->TextInList[Index], + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + return ReturnStatus; +} + + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + @param Private Protocol instance pointer. + @param Key Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR The keydtroke information was not returned due + to hardware errors. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInPrivateReadKeyStroke ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + OUT EFI_INPUT_KEY *Key + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_INPUT_KEY CurrentKey; + + Key->UnicodeChar = 0; + Key->ScanCode = SCAN_NULL; + + // + // if no physical console input device exists, return EFI_NOT_READY; + // if any physical console input device has key input, + // return the key and EFI_SUCCESS. + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextInList[Index]->ReadKeyStroke ( + Private->TextInList[Index], + &CurrentKey + ); + if (!EFI_ERROR (Status)) { + *Key = CurrentKey; + return Status; + } + } + + return EFI_NOT_READY; +} + + + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + @param This Protocol instance pointer. + @param Key Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR The keydtroke information was not returned due + to hardware errors. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + Private->KeyEventSignalState = FALSE; + + // + // Signal ConnectConIn event on first call in Lazy ConIn mode + // + if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) { + DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n")); + gBS->SignalEvent (Private->ConnectConInEvent); + mConInIsConnect = TRUE; + } + + return ConSplitterTextInPrivateReadKeyStroke (Private, Key); +} + + +/** + This event aggregates all the events of the ConIn devices in the spliter. + + If any events of physical ConIn devices are signaled, signal the ConIn + spliter event. This will cause the calling code to call + ConSplitterTextInReadKeyStroke (). + + @param Event The Event assoicated with callback. + @param Context Context registered when Event was created. + +**/ +VOID +EFIAPI +ConSplitterTextInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context; + + if (Private->KeyEventSignalState) { + // + // If KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke() + // + gBS->SignalEvent (Event); + return ; + } + + // + // If any physical console input device has key input, signal the event. + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (Event); + Private->KeyEventSignalState = TRUE; + } + } +} + + + +/** + Test if the key has been registered on input device. + + @param RegsiteredData A pointer to a buffer that is filled in with the + keystroke state data for the key that was + registered. + @param InputData A pointer to a buffer that is filled in with the + keystroke state data for the key that was + pressed. + + @retval TRUE Key be pressed matches a registered key. + @retval FLASE Match failed. + +**/ +BOOLEAN +IsKeyRegistered ( + IN EFI_KEY_DATA *RegsiteredData, + IN EFI_KEY_DATA *InputData + ) +{ + ASSERT (RegsiteredData != NULL && InputData != NULL); + + if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) || + (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) { + return FALSE; + } + + // + // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored. + // + if (RegsiteredData->KeyState.KeyShiftState != 0 && + RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) { + return FALSE; + } + if (RegsiteredData->KeyState.KeyToggleState != 0 && + RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) { + return FALSE; + } + + return TRUE; + +} + + +/** + Reset the input device and optionaly run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInResetEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + Private->KeyEventSignalState = FALSE; + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) { + Status = Private->TextInExList[Index]->Reset ( + Private->TextInExList[Index], + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + return ReturnStatus; + +} + + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + @param This Protocol instance pointer. + @param KeyData A pointer to a buffer that is filled in with the + keystroke state data for the key that was + pressed. + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR The keystroke information was not returned due + to hardware errors. + @retval EFI_INVALID_PARAMETER KeyData is NULL. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInReadKeyStrokeEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData + ) +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + EFI_STATUS Status; + UINTN Index; + EFI_KEY_DATA CurrentKeyData; + + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + Private->KeyEventSignalState = FALSE; + + KeyData->Key.UnicodeChar = 0; + KeyData->Key.ScanCode = SCAN_NULL; + + // + // Signal ConnectConIn event on first call in Lazy ConIn mode + // + if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) { + DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n")); + gBS->SignalEvent (Private->ConnectConInEvent); + mConInIsConnect = TRUE; + } + + // + // if no physical console input device exists, return EFI_NOT_READY; + // if any physical console input device has key input, + // return the key and EFI_SUCCESS. + // + for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) { + Status = Private->TextInExList[Index]->ReadKeyStrokeEx ( + Private->TextInExList[Index], + &CurrentKeyData + ); + if (!EFI_ERROR (Status)) { + CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData)); + return Status; + } + } + + return EFI_NOT_READY; +} + + +/** + Set certain state for the input device. + + @param This Protocol instance pointer. + @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the + state for the input device. + + @retval EFI_SUCCESS The device state was set successfully. + @retval EFI_DEVICE_ERROR The device is not functioning correctly and + could not have the setting adjusted. + @retval EFI_UNSUPPORTED The device does not have the ability to set its + state. + @retval EFI_INVALID_PARAMETER KeyToggleState is NULL. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState + ) +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + EFI_STATUS Status; + UINTN Index; + + if (KeyToggleState == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // if no physical console input device exists, return EFI_SUCCESS; + // otherwise return the status of setting state of physical console input device + // + for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) { + Status = Private->TextInExList[Index]->SetState ( + Private->TextInExList[Index], + KeyToggleState + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; + +} + + +/** + Register a notification function for a particular keystroke for the input device. + + @param This Protocol instance pointer. + @param KeyData A pointer to a buffer that is filled in with the + keystroke information data for the key that was + pressed. + @param KeyNotificationFunction Points to the function to be called when the key + sequence is typed specified by KeyData. + @param NotifyHandle Points to the unique handle assigned to the + registered notification. + + @retval EFI_SUCCESS The notification function was registered + successfully. + @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data + structures. + @retval EFI_INVALID_PARAMETER KeyData or KeyNotificationFunction or NotifyHandle is NULL. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInRegisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT VOID **NotifyHandle + ) +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + EFI_STATUS Status; + UINTN Index; + TEXT_IN_EX_SPLITTER_NOTIFY *NewNotify; + LIST_ENTRY *Link; + TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify; + + + if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. + // + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link); + if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { + *NotifyHandle = CurrentNotify; + return EFI_SUCCESS; + } + } + } + + // + // Allocate resource to save the notification function + // + NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY)); + if (NewNotify == NULL) { + return EFI_OUT_OF_RESOURCES; + } + NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->TextInExListCount); + if (NewNotify->NotifyHandleList == NULL) { + gBS->FreePool (NewNotify); + return EFI_OUT_OF_RESOURCES; + } + NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE; + NewNotify->KeyNotificationFn = KeyNotificationFunction; + CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA)); + + // + // Return the wrong status of registering key notify of + // physical console input device if meet problems + // + for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) { + Status = Private->TextInExList[Index]->RegisterKeyNotify ( + Private->TextInExList[Index], + KeyData, + KeyNotificationFunction, + &NewNotify->NotifyHandleList[Index] + ); + if (EFI_ERROR (Status)) { + // + // Un-register the key notify on all physical console input devices + // + while (Index-- != 0) { + Private->TextInExList[Index]->UnregisterKeyNotify ( + Private->TextInExList[Index], + NewNotify->NotifyHandleList[Index] + ); + } + gBS->FreePool (NewNotify->NotifyHandleList); + gBS->FreePool (NewNotify); + return Status; + } + } + + InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry); + + *NotifyHandle = NewNotify; + + return EFI_SUCCESS; + +} + + +/** + Remove a registered notification function from a particular keystroke. + + @param This Protocol instance pointer. + @param NotificationHandle The handle of the notification function being + unregistered. + + @retval EFI_SUCCESS The notification function was unregistered + successfully. + @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInUnregisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN VOID *NotificationHandle + ) +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify; + LIST_ENTRY *Link; + + if (NotificationHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { + CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link); + if (CurrentNotify == NotificationHandle) { + for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) { + Private->TextInExList[Index]->UnregisterKeyNotify ( + Private->TextInExList[Index], + CurrentNotify->NotifyHandleList[Index] + ); + } + RemoveEntryList (&CurrentNotify->NotifyEntry); + + gBS->FreePool (CurrentNotify->NotifyHandleList); + gBS->FreePool (CurrentNotify); + return EFI_SUCCESS; + } + } + + // + // NotificationHandle is not found in database + // + return EFI_INVALID_PARAMETER; +} + + +/** + Reset the input device and optionaly run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +EFI_STATUS +EFIAPI +ConSplitterSimplePointerReset ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This); + + Private->InputEventSignalState = FALSE; + + if (Private->CurrentNumberOfPointers == 0) { + return EFI_SUCCESS; + } + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) { + Status = Private->PointerList[Index]->Reset ( + Private->PointerList[Index], + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + return ReturnStatus; +} + + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + @param Private Protocol instance pointer. + @param State The state information of simple pointer device. + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR The keydtroke information was not returned due + to hardware errors. + +**/ +EFI_STATUS +EFIAPI +ConSplitterSimplePointerPrivateGetState ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ) +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + UINTN Index; + EFI_SIMPLE_POINTER_STATE CurrentState; + + State->RelativeMovementX = 0; + State->RelativeMovementY = 0; + State->RelativeMovementZ = 0; + State->LeftButton = FALSE; + State->RightButton = FALSE; + + // + // if no physical console input device exists, return EFI_NOT_READY; + // if any physical console input device has key input, + // return the key and EFI_SUCCESS. + // + ReturnStatus = EFI_NOT_READY; + for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) { + + Status = Private->PointerList[Index]->GetState ( + Private->PointerList[Index], + &CurrentState + ); + if (!EFI_ERROR (Status)) { + if (ReturnStatus == EFI_NOT_READY) { + ReturnStatus = EFI_SUCCESS; + } + + if (CurrentState.LeftButton) { + State->LeftButton = TRUE; + } + + if (CurrentState.RightButton) { + State->RightButton = TRUE; + } + + if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) { + State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX; + } + + if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) { + State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY; + } + + if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) { + State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ; + } + } else if (Status == EFI_DEVICE_ERROR) { + ReturnStatus = EFI_DEVICE_ERROR; + } + } + + return ReturnStatus; +} + + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + @param This A pointer to protocol instance. + @param State A pointer to state information on the pointer device + + @retval EFI_SUCCESS The keystroke information was returned in State. + @retval EFI_NOT_READY There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR The keydtroke information was not returned due + to hardware errors. + +**/ +EFI_STATUS +EFIAPI +ConSplitterSimplePointerGetState ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ) +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This); + + Private->InputEventSignalState = FALSE; + + return ConSplitterSimplePointerPrivateGetState (Private, State); +} + + +/** + This event agregates all the events of the ConIn devices in the spliter. + If any events of physical ConIn devices are signaled, signal the ConIn + spliter event. This will cause the calling code to call + ConSplitterTextInReadKeyStroke (). + + @param Event The Event assoicated with callback. + @param Context Context registered when Event was created. + +**/ +VOID +EFIAPI +ConSplitterSimplePointerWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context; + + // + // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke() + // + if (Private->InputEventSignalState) { + gBS->SignalEvent (Event); + return ; + } + // + // if any physical console input device has key input, signal the event. + // + for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) { + Status = gBS->CheckEvent (Private->PointerList[Index]->WaitForInput); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (Event); + Private->InputEventSignalState = TRUE; + } + } +} + +/** + Resets the pointer device hardware. + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning correctly and + could not be reset. + +**/ +EFI_STATUS +EFIAPI +ConSplitterAbsolutePointerReset ( + IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This); + + Private->AbsoluteInputEventSignalState = FALSE; + + if (Private->CurrentNumberOfAbsolutePointers == 0) { + return EFI_SUCCESS; + } + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfAbsolutePointers; Index++) { + Status = Private->AbsolutePointerList[Index]->Reset ( + Private->AbsolutePointerList[Index], + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + return ReturnStatus; +} + + +/** + Retrieves the current state of a pointer device. + + @param This Protocol instance pointer. + @param State A pointer to the state information on the + pointer device. + + @retval EFI_SUCCESS The state of the pointer device was returned in + State.. + @retval EFI_NOT_READY The state of the pointer device has not changed + since the last call to GetState(). + @retval EFI_DEVICE_ERROR A device error occurred while attempting to + retrieve the pointer device's current state. + +**/ +EFI_STATUS +EFIAPI +ConSplitterAbsolutePointerGetState ( + IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, + IN OUT EFI_ABSOLUTE_POINTER_STATE *State + ) +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + UINTN Index; + EFI_ABSOLUTE_POINTER_STATE CurrentState; + + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This); + + Private->AbsoluteInputEventSignalState = FALSE; + + State->CurrentX = 0; + State->CurrentY = 0; + State->CurrentZ = 0; + State->ActiveButtons = 0; + + // + // if no physical pointer device exists, return EFI_NOT_READY; + // if any physical pointer device has changed state, + // return the state and EFI_SUCCESS. + // + ReturnStatus = EFI_NOT_READY; + for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) { + + Status = Private->AbsolutePointerList[Index]->GetState ( + Private->AbsolutePointerList[Index], + &CurrentState + ); + if (!EFI_ERROR (Status)) { + if (ReturnStatus == EFI_NOT_READY) { + ReturnStatus = EFI_SUCCESS; + } + + State->ActiveButtons = CurrentState.ActiveButtons; + + if (!(Private->AbsolutePointerMode.AbsoluteMinX == 0 && Private->AbsolutePointerMode.AbsoluteMaxX == 0)) { + State->CurrentX = CurrentState.CurrentX; + } + if (!(Private->AbsolutePointerMode.AbsoluteMinY == 0 && Private->AbsolutePointerMode.AbsoluteMaxY == 0)) { + State->CurrentY = CurrentState.CurrentY; + } + if (!(Private->AbsolutePointerMode.AbsoluteMinZ == 0 && Private->AbsolutePointerMode.AbsoluteMaxZ == 0)) { + State->CurrentZ = CurrentState.CurrentZ; + } + + } else if (Status == EFI_DEVICE_ERROR) { + ReturnStatus = EFI_DEVICE_ERROR; + } + } + + return ReturnStatus; +} + + +/** + This event agregates all the events of the pointer devices in the splitter. + If any events of physical pointer devices are signaled, signal the pointer + splitter event. This will cause the calling code to call + ConSplitterAbsolutePointerGetState (). + + @param Event The Event assoicated with callback. + @param Context Context registered when Event was created. + +**/ +VOID +EFIAPI +ConSplitterAbsolutePointerWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context; + + // + // if AbsoluteInputEventSignalState is flagged before, + // and not cleared by Reset() or GetState(), signal it + // + if (Private->AbsoluteInputEventSignalState) { + gBS->SignalEvent (Event); + return ; + } + // + // if any physical console input device has key input, signal the event. + // + for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) { + Status = gBS->CheckEvent (Private->AbsolutePointerList[Index]->WaitForInput); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (Event); + Private->AbsoluteInputEventSignalState = TRUE; + } + } +} + + +/** + Reset the text output device hardware and optionaly run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform more exhaustive verfication + operation of the device during reset. + + @retval EFI_SUCCESS The text output device was reset. + @retval EFI_DEVICE_ERROR The text output device is not functioning + correctly and could not be reset. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextOutList[Index].TextOut->Reset ( + Private->TextOutList[Index].TextOut, + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BLACK)); + + // + // reset all mode parameters + // + TextOutSetMode (Private, 0); + + return ReturnStatus; +} + + +/** + Write a Unicode string to the output device. + + @param This Protocol instance pointer. + @param WString The NULL-terminated Unicode string to be + displayed on the output device(s). All output + devices must also support the Unicode drawing + defined in this file. + + @retval EFI_SUCCESS The string was output to the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to + output the text. + @retval EFI_UNSUPPORTED The output device's mode is not currently in a + defined text mode. + @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + UINTN MaxColumn; + UINTN MaxRow; + + This->SetAttribute (This, This->Mode->Attribute); + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextOutList[Index].TextOut->OutputString ( + Private->TextOutList[Index].TextOut, + WString + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + if (Private->CurrentNumberOfConsoles > 0) { + Private->TextOutMode.CursorColumn = Private->TextOutList[0].TextOut->Mode->CursorColumn; + Private->TextOutMode.CursorRow = Private->TextOutList[0].TextOut->Mode->CursorRow; + } else { + // + // When there is no real console devices in system, + // update cursor position for the virtual device in consplitter. + // + Private->TextOut.QueryMode ( + &Private->TextOut, + Private->TextOutMode.Mode, + &MaxColumn, + &MaxRow + ); + for (; *WString != CHAR_NULL; WString++) { + switch (*WString) { + case CHAR_BACKSPACE: + if (Private->TextOutMode.CursorColumn == 0 && Private->TextOutMode.CursorRow > 0) { + Private->TextOutMode.CursorRow--; + Private->TextOutMode.CursorColumn = (INT32) (MaxColumn - 1); + } else if (Private->TextOutMode.CursorColumn > 0) { + Private->TextOutMode.CursorColumn--; + } + break; + + case CHAR_LINEFEED: + if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) { + Private->TextOutMode.CursorRow++; + } + break; + + case CHAR_CARRIAGE_RETURN: + Private->TextOutMode.CursorColumn = 0; + break; + + default: + if (Private->TextOutMode.CursorColumn < (INT32) (MaxColumn - 1)) { + Private->TextOutMode.CursorColumn++; + } else { + Private->TextOutMode.CursorColumn = 0; + if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) { + Private->TextOutMode.CursorRow++; + } + } + break; + } + } + } + + return ReturnStatus; +} + + +/** + Verifies that all characters in a Unicode string can be output to the + target device. + + @param This Protocol instance pointer. + @param WString The NULL-terminated Unicode string to be + examined for the output device(s). + + @retval EFI_SUCCESS The device(s) are capable of rendering the + output string. + @retval EFI_UNSUPPORTED Some of the characters in the Unicode string + cannot be rendered by one or more of the output + devices mapped by the EFI handle. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextOutList[Index].TextOut->TestString ( + Private->TextOutList[Index].TextOut, + WString + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + // + // There is no DevNullTextOutTestString () since a Unicode buffer would + // always return EFI_SUCCESS. + // ReturnStatus will be EFI_SUCCESS if no consoles are present + // + return ReturnStatus; +} + + +/** + Returns information for an available text mode that the output device(s) + supports. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param Columns Returns the columns of the text output device + for the requested ModeNumber. + @param Rows Returns the rows of the text output device + for the requested ModeNumber. + + @retval EFI_SUCCESS The requested mode information was returned. + @retval EFI_DEVICE_ERROR The device had an error and could not complete + the request. + @retval EFI_UNSUPPORTED The mode number was not valid. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +{ + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN CurrentMode; + INT32 *TextOutModeMap; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // Check whether param ModeNumber is valid. + // ModeNumber should be within range 0 ~ MaxMode - 1. + // + if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) { + return EFI_UNSUPPORTED; + } + + if ((INT32) ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + // + // We get the available mode from mode intersection map if it's available + // + if (Private->TextOutModeMap != NULL) { + TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber; + CurrentMode = (UINTN)(*TextOutModeMap); + *Columns = Private->TextOutQueryData[CurrentMode].Columns; + *Rows = Private->TextOutQueryData[CurrentMode].Rows; + } else { + *Columns = Private->TextOutQueryData[ModeNumber].Columns; + *Rows = Private->TextOutQueryData[ModeNumber].Rows; + } + + if (*Columns <= 0 && *Rows <= 0) { + return EFI_UNSUPPORTED; + + } + + return EFI_SUCCESS; +} + + +/** + Sets the output device(s) to a specified mode. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to set. + + @retval EFI_SUCCESS The requested text mode was set. + @retval EFI_DEVICE_ERROR The device had an error and could not complete + the request. + @retval EFI_UNSUPPORTED The mode number was not valid. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + INT32 *TextOutModeMap; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // Check whether param ModeNumber is valid. + // ModeNumber should be within range 0 ~ MaxMode - 1. + // + if ( (ModeNumber > (UINTN)(((UINT32)-1)>>1)) ) { + return EFI_UNSUPPORTED; + } + + if ((INT32) ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + // + // If the mode is being set to the curent mode, then just clear the screen and return. + // + if (Private->TextOutMode.Mode == (INT32) ModeNumber) { + return ConSplitterTextOutClearScreen (This); + } + // + // return the worst status met + // + TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber; + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextOutList[Index].TextOut->SetMode ( + Private->TextOutList[Index].TextOut, + TextOutModeMap[Index] + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + // + // Set mode parameter to specified mode number + // + TextOutSetMode (Private, ModeNumber); + + return ReturnStatus; +} + + +/** + Sets the background and foreground colors for the OutputString () and + ClearScreen () functions. + + @param This Protocol instance pointer. + @param Attribute The attribute to set. Bits 0..3 are the + foreground color, and bits 4..6 are the + background color. All other bits are undefined + and must be zero. The valid Attributes are + defined in this file. + + @retval EFI_SUCCESS The attribute was set. + @retval EFI_DEVICE_ERROR The device had an error and could not complete + the request. + @retval EFI_UNSUPPORTED The attribute requested is not defined. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ) +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // Check whether param Attribute is valid. + // + if ( (Attribute > (UINTN)(((UINT32)-1)>>1)) ) { + return EFI_UNSUPPORTED; + } + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextOutList[Index].TextOut->SetAttribute ( + Private->TextOutList[Index].TextOut, + Attribute + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + Private->TextOutMode.Attribute = (INT32) Attribute; + + return ReturnStatus; +} + + +/** + Clears the output device(s) display to the currently selected background + color. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete + the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + // + // No need to do extra check here as whether (Column, Row) is valid has + // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should + // always be supported. + // + Private->TextOutMode.CursorColumn = 0; + Private->TextOutMode.CursorRow = 0; + Private->TextOutMode.CursorVisible = TRUE; + + return ReturnStatus; +} + + +/** + Sets the current coordinates of the cursor position + + @param This Protocol instance pointer. + @param Column The column position to set the cursor to. Must be + greater than or equal to zero and less than the + number of columns by QueryMode (). + @param Row The row position to set the cursor to. Must be + greater than or equal to zero and less than the + number of rows by QueryMode (). + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete + the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode, + or the cursor position is invalid for the + current mode. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + UINTN MaxColumn; + UINTN MaxRow; + INT32 *TextOutModeMap; + INT32 ModeNumber; + INT32 CurrentMode; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + TextOutModeMap = NULL; + ModeNumber = Private->TextOutMode.Mode; + + // + // Get current MaxColumn and MaxRow from intersection map + // + if (Private->TextOutModeMap != NULL) { + TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber; + CurrentMode = *TextOutModeMap; + } else { + CurrentMode = ModeNumber; + } + + MaxColumn = Private->TextOutQueryData[CurrentMode].Columns; + MaxRow = Private->TextOutQueryData[CurrentMode].Rows; + + if (Column >= MaxColumn || Row >= MaxRow) { + return EFI_UNSUPPORTED; + } + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextOutList[Index].TextOut->SetCursorPosition ( + Private->TextOutList[Index].TextOut, + Column, + Row + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + // + // No need to do extra check here as whether (Column, Row) is valid has + // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should + // always be supported. + // + Private->TextOutMode.CursorColumn = (INT32) Column; + Private->TextOutMode.CursorRow = (INT32) Row; + + return ReturnStatus; +} + + +/** + Makes the cursor visible or invisible + + @param This Protocol instance pointer. + @param Visible If TRUE, the cursor is set to be visible. If + FALSE, the cursor is set to be invisible. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete + the request, or the device does not support + changing the cursor mode. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextOutList[Index].TextOut->EnableCursor ( + Private->TextOutList[Index].TextOut, + Visible + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + Private->TextOutMode.CursorVisible = Visible; + + return ReturnStatus; +} + + +/** + An empty function to pass error checking of CreateEventEx (). + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context, + which is implementation-dependent. + +**/ +VOID +EFIAPI +ConSplitterEmptyCallbackFunction ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ +} diff --git a/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h b/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h new file mode 100644 index 0000000000..e32abbaea1 --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h @@ -0,0 +1,2004 @@ +/** @file + Private data structures for the Console Splitter driver + +Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _CON_SPLITTER_H_ +#define _CON_SPLITTER_H_ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Driver Binding Externs +// +extern EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConSplitterConInComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gConSplitterConInComponentName2; +extern EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConSplitterSimplePointerComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gConSplitterSimplePointerComponentName2; +extern EFI_DRIVER_BINDING_PROTOCOL gConSplitterAbsolutePointerDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConSplitterAbsolutePointerComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gConSplitterAbsolutePointerComponentName2; +extern EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConSplitterConOutComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gConSplitterConOutComponentName2; +extern EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gConSplitterStdErrComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gConSplitterStdErrComponentName2; + + +// +// These definitions were in the old Hii protocol, but are not in the new UEFI +// version. So they are defined locally. +// +#define UNICODE_NARROW_CHAR 0xFFF0 +#define UNICODE_WIDE_CHAR 0xFFF1 + + +// +// Private Data Structures +// +#define CONSOLE_SPLITTER_ALLOC_UNIT 32 + + +typedef struct { + UINTN Column; + UINTN Row; +} CONSOLE_OUT_MODE; + +typedef struct { + UINTN Columns; + UINTN Rows; +} TEXT_OUT_SPLITTER_QUERY_DATA; + + +#define TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE SIGNATURE_32 ('T', 'i', 'S', 'n') + +// +// Private data for Text In Ex Splitter Notify +// +typedef struct _TEXT_IN_EX_SPLITTER_NOTIFY { + UINTN Signature; + VOID **NotifyHandleList; + EFI_KEY_DATA KeyData; + EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; + LIST_ENTRY NotifyEntry; +} TEXT_IN_EX_SPLITTER_NOTIFY; + +#define TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS(a) \ + CR ((a), \ + TEXT_IN_EX_SPLITTER_NOTIFY, \ + NotifyEntry, \ + TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE \ + ) + +#define TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('T', 'i', 'S', 'p') + +// +// Private data for the Console In splitter +// +typedef struct { + UINT64 Signature; + EFI_HANDLE VirtualHandle; + + EFI_SIMPLE_TEXT_INPUT_PROTOCOL TextIn; + UINTN CurrentNumberOfConsoles; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL **TextInList; + UINTN TextInListCount; + + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL TextInEx; + UINTN CurrentNumberOfExConsoles; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **TextInExList; + UINTN TextInExListCount; + LIST_ENTRY NotifyList; + + + EFI_SIMPLE_POINTER_PROTOCOL SimplePointer; + EFI_SIMPLE_POINTER_MODE SimplePointerMode; + UINTN CurrentNumberOfPointers; + EFI_SIMPLE_POINTER_PROTOCOL **PointerList; + UINTN PointerListCount; + + EFI_ABSOLUTE_POINTER_PROTOCOL AbsolutePointer; + EFI_ABSOLUTE_POINTER_MODE AbsolutePointerMode; + UINTN CurrentNumberOfAbsolutePointers; + EFI_ABSOLUTE_POINTER_PROTOCOL **AbsolutePointerList; + UINTN AbsolutePointerListCount; + BOOLEAN AbsoluteInputEventSignalState; + + BOOLEAN KeyEventSignalState; + BOOLEAN InputEventSignalState; + EFI_EVENT ConnectConInEvent; +} TEXT_IN_SPLITTER_PRIVATE_DATA; + +#define TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR ((a), \ + TEXT_IN_SPLITTER_PRIVATE_DATA, \ + TextIn, \ + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS(a) \ + CR ((a), \ + TEXT_IN_SPLITTER_PRIVATE_DATA, \ + SimplePointer, \ + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) +#define TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + TEXT_IN_SPLITTER_PRIVATE_DATA, \ + TextInEx, \ + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS(a) \ + CR (a, \ + TEXT_IN_SPLITTER_PRIVATE_DATA, \ + AbsolutePointer, \ + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + + +#define TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('T', 'o', 'S', 'p') + +typedef struct { + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; +} TEXT_OUT_AND_GOP_DATA; + +// +// Private data for the Console Out splitter +// +typedef struct { + UINT64 Signature; + EFI_HANDLE VirtualHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL TextOut; + EFI_SIMPLE_TEXT_OUTPUT_MODE TextOutMode; + + EFI_UGA_DRAW_PROTOCOL UgaDraw; + UINT32 UgaHorizontalResolution; + UINT32 UgaVerticalResolution; + UINT32 UgaColorDepth; + UINT32 UgaRefreshRate; + + EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GraphicsOutputModeBuffer; + UINTN CurrentNumberOfGraphicsOutput; + UINTN CurrentNumberOfUgaDraw; + + UINTN CurrentNumberOfConsoles; + TEXT_OUT_AND_GOP_DATA *TextOutList; + UINTN TextOutListCount; + TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData; + UINTN TextOutQueryDataCount; + INT32 *TextOutModeMap; + +} TEXT_OUT_SPLITTER_PRIVATE_DATA; + +#define TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR ((a), \ + TEXT_OUT_SPLITTER_PRIVATE_DATA, \ + TextOut, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR ((a), \ + TEXT_OUT_SPLITTER_PRIVATE_DATA, \ + GraphicsOutput, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR ((a), \ + TEXT_OUT_SPLITTER_PRIVATE_DATA, \ + UgaDraw, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR ((a), \ + TEXT_OUT_SPLITTER_PRIVATE_DATA, \ + ConsoleControl, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +// +// Function Prototypes +// + +/** + The user Entry Point for module ConSplitter. The user code starts with this function. + + Installs driver module protocols and. Creates virtual device handles for ConIn, + ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol, + Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers. + Installs Graphics Output protocol and/or UGA Draw protocol if needed. + + @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 +ConSplitterDriverEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Construct console input devices' private data. + + @param ConInPrivate A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA + structure. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS Text Input Devcie's private data has been constructed. + @retval other Failed to construct private data. + +**/ +EFI_STATUS +ConSplitterTextInConstructor ( + TEXT_IN_SPLITTER_PRIVATE_DATA *ConInPrivate + ); + +/** + Construct console output devices' private data. + + @param ConOutPrivate A pointer to the TEXT_OUT_SPLITTER_PRIVATE_DATA + structure. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS Text Input Devcie's private data has been constructed. + +**/ +EFI_STATUS +ConSplitterTextOutConstructor ( + TEXT_OUT_SPLITTER_PRIVATE_DATA *ConOutPrivate + ); + + +/** + Test to see if Console In Device could be supported on the Controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Test to see if Simple Pointer protocol could be supported on the Controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Test to see if Console Out Device could be supported on the Controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Test to see if Standard Error Device could be supported on the Controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Start Console In Consplitter on device handle. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS Console In Consplitter is added to ControllerHandle. + @retval other Console In Consplitter does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Start Simple Pointer Consplitter on device handle. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS Simple Pointer Consplitter is added to ControllerHandle. + @retval other Simple Pointer Consplitter does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Start Console Out Consplitter on device handle. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS Console Out Consplitter is added to ControllerHandle. + @retval other Console Out Consplitter does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Start Standard Error Consplitter on device handle. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS Standard Error Consplitter is added to ControllerHandle. + @retval other Standard Error Consplitter does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop Console In ConSplitter on ControllerHandle by closing Console In Devcice GUID. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +/** + Stop Simple Pointer protocol ConSplitter on ControllerHandle by closing + Simple Pointer protocol. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +/** + Stop Console Out ConSplitter on device handle by closing Console Out Devcice GUID. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +/** + Stop Standard Error ConSplitter on ControllerHandle by closing Standard Error GUID. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + + +/** + Test to see if Absolute Pointer protocol could be supported on the Controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterAbsolutePointerDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Start Absolute Pointer Consplitter on device handle. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS Absolute Pointer Consplitter is added to ControllerHandle. + @retval other Absolute Pointer Consplitter does not support this device. + +**/ +EFI_STATUS +EFIAPI +ConSplitterAbsolutePointerDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop Absolute Pointer protocol ConSplitter on ControllerHandle by closing + Absolute Pointer protocol. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +ConSplitterAbsolutePointerDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +/** + Add Absolute Pointer Device in Consplitter Absolute Pointer list. + + @param Private Text In Splitter pointer. + @param AbsolutePointer Absolute Pointer protocol pointer. + + @retval EFI_SUCCESS Absolute Pointer Device added successfully. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterAbsolutePointerAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer + ); + +/** + Remove Absolute Pointer Device from Consplitter Absolute Pointer list. + + @param Private Text In Splitter pointer. + @param AbsolutePointer Absolute Pointer protocol pointer. + + @retval EFI_SUCCESS Absolute Pointer Device removed successfully. + @retval EFI_NOT_FOUND No Absolute Pointer Device found. + +**/ +EFI_STATUS +ConSplitterAbsolutePointerDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer + ); + +// +// Absolute Pointer protocol interfaces +// + + +/** + Resets the pointer device hardware. + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning correctly and + could not be reset. + +**/ +EFI_STATUS +EFIAPI +ConSplitterAbsolutePointerReset ( + IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + + +/** + Retrieves the current state of a pointer device. + + @param This Protocol instance pointer. + @param State A pointer to the state information on the + pointer device. + + @retval EFI_SUCCESS The state of the pointer device was returned in + State.. + @retval EFI_NOT_READY The state of the pointer device has not changed + since the last call to GetState(). + @retval EFI_DEVICE_ERROR A device error occurred while attempting to + retrieve the pointer device's current state. + +**/ +EFI_STATUS +EFIAPI +ConSplitterAbsolutePointerGetState ( + IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, + IN OUT EFI_ABSOLUTE_POINTER_STATE *State + ); + +/** + This event agregates all the events of the pointer devices in the splitter. + + If any events of physical pointer devices are signaled, signal the pointer + splitter event. This will cause the calling code to call + ConSplitterAbsolutePointerGetState (). + + @param Event The Event assoicated with callback. + @param Context Context registered when Event was created. + +**/ +VOID +EFIAPI +ConSplitterAbsolutePointerWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + 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 +ConSplitterComponentNameGetDriverName ( + 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 NULL. + + @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 +ConSplitterConInComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +/** + 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 NULL. + + @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 +ConSplitterSimplePointerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL + instance. + @param ControllerHandle 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 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 A pointer to RFC4646 language identifier. This is + the language of the controller name that 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. + @param ControllerName 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 NULL. + @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 +ConSplitterAbsolutePointerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +/** + 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 NULL. + + @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 +ConSplitterConOutComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +/** + 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 NULL. + + @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 +ConSplitterStdErrComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +// +// TextIn Constructor/Destructor functions +// + +/** + Add Text Input Device in Consplitter Text Input list. + + @param Private Text In Splitter pointer. + @param TextIn Simple Text Input protocol pointer. + + @retval EFI_SUCCESS Text Input Device added successfully. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterTextInAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn + ); + +/** + Remove Text Input Device from Consplitter Text Input list. + + @param Private Text In Splitter pointer. + @param TextIn Simple Text protocol pointer. + + @retval EFI_SUCCESS Simple Text Device removed successfully. + @retval EFI_NOT_FOUND No Simple Text Device found. + +**/ +EFI_STATUS +ConSplitterTextInDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn + ); + +// +// SimplePointer Constuctor/Destructor functions +// + +/** + Add Simple Pointer Device in Consplitter Simple Pointer list. + + @param Private Text In Splitter pointer. + @param SimplePointer Simple Pointer protocol pointer. + + @retval EFI_SUCCESS Simple Pointer Device added successfully. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterSimplePointerAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer + ); + +/** + Remove Simple Pointer Device from Consplitter Simple Pointer list. + + @param Private Text In Splitter pointer. + @param SimplePointer Simple Pointer protocol pointer. + + @retval EFI_SUCCESS Simple Pointer Device removed successfully. + @retval EFI_NOT_FOUND No Simple Pointer Device found. + +**/ +EFI_STATUS +ConSplitterSimplePointerDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer + ); + +// +// TextOut Constuctor/Destructor functions +// + +/** + Add Text Output Device in Consplitter Text Output list. + + @param Private Text Out Splitter pointer. + @param TextOut Simple Text Output protocol pointer. + @param GraphicsOutput Graphics Output protocol pointer. + @param UgaDraw UGA Draw protocol pointer. + + @retval EFI_SUCCESS Text Output Device added successfully. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterTextOutAddDevice ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut, + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw + ); + +/** + Remove Text Out Device in Consplitter Text Out list. + + @param Private Text Out Splitter pointer. + @param TextOut Simple Text Output Pointer protocol pointer. + + @retval EFI_SUCCESS Text Out Device removed successfully. + @retval EFI_NOT_FOUND No Text Out Device found. + +**/ +EFI_STATUS +ConSplitterTextOutDeleteDevice ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut + ); + +// +// TextIn I/O Functions +// + +/** + Reset the input device and optionaly run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInReset ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + @param This Protocol instance pointer. + @param Key Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR The keydtroke information was not returned due + to hardware errors. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ); + +/** + Add Text Input Ex Device in Consplitter Text Input Ex list. + + @param Private Text In Splitter pointer. + @param TextInEx Simple Text Input Ex Input protocol pointer. + + @retval EFI_SUCCESS Text Input Ex Device added successfully. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterTextInExAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx + ); + +/** + Remove Text Ex Device from Consplitter Text Input Ex list. + + @param Private Text In Splitter pointer. + @param TextInEx Simple Text Ex protocol pointer. + + @retval EFI_SUCCESS Simple Text Input Ex Device removed successfully. + @retval EFI_NOT_FOUND No Simple Text Input Ex Device found. + +**/ +EFI_STATUS +ConSplitterTextInExDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx + ); + +// +// Simple Text Input Ex protocol function prototypes +// + +/** + Reset the input device and optionaly run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInResetEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + @param This Protocol instance pointer. + @param KeyData A pointer to a buffer that is filled in with the + keystroke state data for the key that was + pressed. + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR The keystroke information was not returned due + to hardware errors. + @retval EFI_INVALID_PARAMETER KeyData is NULL. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInReadKeyStrokeEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData + ); + + +/** + Set certain state for the input device. + + @param This Protocol instance pointer. + @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the + state for the input device. + + @retval EFI_SUCCESS The device state was set successfully. + @retval EFI_DEVICE_ERROR The device is not functioning correctly and + could not have the setting adjusted. + @retval EFI_UNSUPPORTED The device does not have the ability to set its + state. + @retval EFI_INVALID_PARAMETER KeyToggleState is NULL. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState + ); + + +/** + Register a notification function for a particular keystroke for the input device. + + @param This Protocol instance pointer. + @param KeyData A pointer to a buffer that is filled in with the + keystroke information data for the key that was + pressed. + @param KeyNotificationFunction Points to the function to be called when the key + sequence is typed specified by KeyData. + @param NotifyHandle Points to the unique handle assigned to the + registered notification. + + @retval EFI_SUCCESS The notification function was registered + successfully. + @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data + structures. + @retval EFI_INVALID_PARAMETER KeyData or KeyNotificationFunction or NotifyHandle is NULL. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInRegisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT VOID **NotifyHandle + ); + + +/** + Remove a registered notification function from a particular keystroke. + + @param This Protocol instance pointer. + @param NotificationHandle The handle of the notification function being + unregistered. + + @retval EFI_SUCCESS The notification function was unregistered + successfully. + @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid. + @retval EFI_NOT_FOUND Can not find the matching entry in database. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInUnregisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN VOID *NotificationHandle + ); + +/** + This event aggregates all the events of the ConIn devices in the spliter. + + If any events of physical ConIn devices are signaled, signal the ConIn + spliter event. This will cause the calling code to call + ConSplitterTextInReadKeyStroke (). + + @param Event The Event assoicated with callback. + @param Context Context registered when Event was created. + +**/ +VOID +EFIAPI +ConSplitterTextInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ); + + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + @param Private Protocol instance pointer. + @param Key Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR The keydtroke information was not returned due + to hardware errors. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextInPrivateReadKeyStroke ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + OUT EFI_INPUT_KEY *Key + ); + +/** + Reset the input device and optionaly run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +EFI_STATUS +EFIAPI +ConSplitterSimplePointerReset ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + @param This A pointer to protocol instance. + @param State A pointer to state information on the pointer device + + @retval EFI_SUCCESS The keystroke information was returned in State. + @retval EFI_NOT_READY There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR The keydtroke information was not returned due + to hardware errors. + +**/ +EFI_STATUS +EFIAPI +ConSplitterSimplePointerGetState ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ); + +/** + This event agregates all the events of the ConIn devices in the spliter. + If any events of physical ConIn devices are signaled, signal the ConIn + spliter event. This will cause the calling code to call + ConSplitterTextInReadKeyStroke (). + + @param Event The Event assoicated with callback. + @param Context Context registered when Event was created. + +**/ +VOID +EFIAPI +ConSplitterSimplePointerWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// TextOut I/O Functions +// + +/** + Reset the text output device hardware and optionaly run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform more exhaustive verfication + operation of the device during reset. + + @retval EFI_SUCCESS The text output device was reset. + @retval EFI_DEVICE_ERROR The text output device is not functioning + correctly and could not be reset. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Write a Unicode string to the output device. + + @param This Protocol instance pointer. + @param WString The NULL-terminated Unicode string to be + displayed on the output device(s). All output + devices must also support the Unicode drawing + defined in this file. + + @retval EFI_SUCCESS The string was output to the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to + output the text. + @retval EFI_UNSUPPORTED The output device's mode is not currently in a + defined text mode. + @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ); + +/** + Verifies that all characters in a Unicode string can be output to the + target device. + + @param This Protocol instance pointer. + @param WString The NULL-terminated Unicode string to be + examined for the output device(s). + + @retval EFI_SUCCESS The device(s) are capable of rendering the + output string. + @retval EFI_UNSUPPORTED Some of the characters in the Unicode string + cannot be rendered by one or more of the output + devices mapped by the EFI handle. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ); + +/** + Returns information for an available text mode that the output device(s) + supports. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param Columns Returns the columns of the text output device + for the requested ModeNumber. + @param Rows Returns the rows of the text output device + for the requested ModeNumber. + + @retval EFI_SUCCESS The requested mode information was returned. + @retval EFI_DEVICE_ERROR The device had an error and could not complete + the request. + @retval EFI_UNSUPPORTED The mode number was not valid. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ); + +/** + Sets the output device(s) to a specified mode. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to set. + + @retval EFI_SUCCESS The requested text mode was set. + @retval EFI_DEVICE_ERROR The device had an error and could not complete + the request. + @retval EFI_UNSUPPORTED The mode number was not valid. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ); + +/** + Sets the background and foreground colors for the OutputString () and + ClearScreen () functions. + + @param This Protocol instance pointer. + @param Attribute The attribute to set. Bits 0..3 are the + foreground color, and bits 4..6 are the + background color. All other bits are undefined + and must be zero. The valid Attributes are + defined in this file. + + @retval EFI_SUCCESS The attribute was set. + @retval EFI_DEVICE_ERROR The device had an error and could not complete + the request. + @retval EFI_UNSUPPORTED The attribute requested is not defined. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ); + +/** + Clears the output device(s) display to the currently selected background + color. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete + the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ); + +/** + Sets the current coordinates of the cursor position + + @param This Protocol instance pointer. + @param Column The column position to set the cursor to. Must be + greater than or equal to zero and less than the + number of columns by QueryMode (). + @param Row The row position to set the cursor to. Must be + greater than or equal to zero and less than the + number of rows by QueryMode (). + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete + the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode, + or the cursor position is invalid for the + current mode. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ); + + +/** + Makes the cursor visible or invisible + + @param This Protocol instance pointer. + @param Visible If TRUE, the cursor is set to be visible. If + FALSE, the cursor is set to be invisible. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete + the request, or the device does not support + changing the cursor mode. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. + +**/ +EFI_STATUS +EFIAPI +ConSplitterTextOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ); + +/** + Take the passed in Buffer of size ElementSize and grow the buffer + by CONSOLE_SPLITTER_ALLOC_UNIT * ElementSize bytes. + Copy the current data in Buffer to the new version of Buffer and + free the old version of buffer. + + @param ElementSize Size of element in array. + @param Count Current number of elements in array. + @param Buffer Bigger version of passed in Buffer with all the + data. + + @retval EFI_SUCCESS Buffer size has grown. + @retval EFI_OUT_OF_RESOURCES Could not grow the buffer size. + +**/ +EFI_STATUS +ConSplitterGrowBuffer ( + IN UINTN ElementSize, + IN OUT UINTN *Count, + IN OUT VOID **Buffer + ); + +/** + Returns information for an available graphics mode that the graphics device + and the set of active video output devices supports. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. + @param Info A pointer to callee allocated buffer that returns information about ModeNumber. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + @retval EFI_OUT_OF_RESOURCES No resource available. + +**/ +EFI_STATUS +EFIAPI +ConSplitterGraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ); + +/** + Set the video device into the specified mode and clears the visible portions of + the output display to black. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber Abstraction that defines the current video mode. + + @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. + @retval EFI_OUT_OF_RESOURCES No resource available. + +**/ +EFI_STATUS +EFIAPI +ConSplitterGraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, + IN UINT32 ModeNumber + ); + +/** + The following table defines actions for BltOperations. + + EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY) + directly to every pixel of the video display rectangle + (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). + Only one pixel will be used from the BltBuffer. Delta is NOT used. + EfiBltVideoToBltBuffer - Read data from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + the BltBuffer rectangle (DestinationX, DestinationY ) + (DestinationX + Width, DestinationY + Height). If DestinationX or + DestinationY is not zero then Delta must be set to the length in bytes + of a row in the BltBuffer. + EfiBltBufferToVideo - Write data from the BltBuffer rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + not zero then Delta must be set to the length in bytes of a row in the + BltBuffer. + EfiBltVideoToVideo - Copy from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) . + to the video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). + The BltBuffer and Delta are not used in this mode. + + @param This Protocol instance pointer. + @param BltBuffer Buffer containing data to blit into video buffer. + This buffer has a size of + Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + @param BltOperation Operation to perform on BlitBuffer and video + memory + @param SourceX X coordinate of source for the BltBuffer. + @param SourceY Y coordinate of source for the BltBuffer. + @param DestinationX X coordinate of destination for the BltBuffer. + @param DestinationY Y coordinate of destination for the BltBuffer. + @param Width Width of rectangle in BltBuffer in pixels. + @param Height Hight of rectangle in BltBuffer in pixels. + @param Delta OPTIONAL. + + @retval EFI_SUCCESS The Blt operation completed. + @retval EFI_INVALID_PARAMETER BltOperation is not valid. + @retval EFI_DEVICE_ERROR A hardware error occured writting to the video + buffer. + +**/ +EFI_STATUS +EFIAPI +ConSplitterGraphicsOutputBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + + +/** + Return the current video mode information. + + @param This The EFI_UGA_DRAW_PROTOCOL instance. + @param HorizontalResolution The size of video screen in pixels in the X dimension. + @param VerticalResolution The size of video screen in pixels in the Y dimension. + @param ColorDepth Number of bits per pixel, currently defined to be 32. + @param RefreshRate The refresh rate of the monitor in Hertz. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +EFI_STATUS +EFIAPI +ConSplitterUgaDrawGetMode ( + IN EFI_UGA_DRAW_PROTOCOL *This, + OUT UINT32 *HorizontalResolution, + OUT UINT32 *VerticalResolution, + OUT UINT32 *ColorDepth, + OUT UINT32 *RefreshRate + ); + +/** + Set the current video mode information. + + @param This The EFI_UGA_DRAW_PROTOCOL instance. + @param HorizontalResolution The size of video screen in pixels in the X dimension. + @param VerticalResolution The size of video screen in pixels in the Y dimension. + @param ColorDepth Number of bits per pixel, currently defined to be 32. + @param RefreshRate The refresh rate of the monitor in Hertz. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_OUT_OF_RESOURCES Out of resources. + +**/ +EFI_STATUS +EFIAPI +ConSplitterUgaDrawSetMode ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ); + +/** + Blt a rectangle of pixels on the graphics screen. + + The following table defines actions for BltOperations. + + EfiUgaVideoFill: + Write data from the BltBuffer pixel (SourceX, SourceY) + directly to every pixel of the video display rectangle + (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). + Only one pixel will be used from the BltBuffer. Delta is NOT used. + EfiUgaVideoToBltBuffer: + Read data from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + the BltBuffer rectangle (DestinationX, DestinationY ) + (DestinationX + Width, DestinationY + Height). If DestinationX or + DestinationY is not zero then Delta must be set to the length in bytes + of a row in the BltBuffer. + EfiUgaBltBufferToVideo: + Write data from the BltBuffer rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + not zero then Delta must be set to the length in bytes of a row in the + BltBuffer. + EfiUgaVideoToVideo: + Copy from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) . + to the video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). + The BltBuffer and Delta are not used in this mode. + + @param This Protocol instance pointer. + @param BltBuffer Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL) + @param BltOperation Operation to perform on BlitBuffer and video memory + @param SourceX X coordinate of source for the BltBuffer. + @param SourceY Y coordinate of source for the BltBuffer. + @param DestinationX X coordinate of destination for the BltBuffer. + @param DestinationY Y coordinate of destination for the BltBuffer. + @param Width Width of rectangle in BltBuffer in pixels. + @param Height Hight of rectangle in BltBuffer in pixels. + @param Delta OPTIONAL + + @retval EFI_SUCCESS The Blt operation completed. + @retval EFI_INVALID_PARAMETER BltOperation is not valid. + @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer. + +**/ +EFI_STATUS +EFIAPI +ConSplitterUgaDrawBlt ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL + IN EFI_UGA_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + +/** + Sets the output device(s) to a specified mode. + + @param Private Text Out Splitter pointer. + @param ModeNumber The mode number to set. + +**/ +VOID +TextOutSetMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN UINTN ModeNumber + ); + +/** + An empty function to pass error checking of CreateEventEx (). + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context, + which is implementation-dependent. + +**/ +VOID +EFIAPI +ConSplitterEmptyCallbackFunction ( + IN EFI_EVENT Event, + IN VOID *Context + ); + + +#endif diff --git a/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf b/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf new file mode 100644 index 0000000000..4885dc7fe9 --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf @@ -0,0 +1,96 @@ +## @file +# This driver provides multi console supports. +# +# This driver acts as a virtual console, takes over the console I/O control from selected +# standard console devices, and transmits console I/O to related console device drivers. +# Consplitter could install Graphics Output protocol and/or UGA Draw protocol in system +# table according PCD settings(PcdConOutGopSupport, and PcdConOutUgaSupport). It always +# consumes Graphics Output protocol which is produced by display device, and consumes UGA Draw +# protocol which is produced by display device according to PcdUgaConsumeSupport value. +# Note: If only UGA Draw protocol is installed in system table, PcdUgaConsumeSupport +# should be set to TRUE. +# +# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ConSplitterDxe + FILE_GUID = 408edcec-cf6d-477c-a5a8-b4844e3de281 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = ConSplitterDriverEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gConSplitterConInDriverBinding +# COMPONENT_NAME = gConSplitterConInComponentName +# COMPONENT_NAME2 = gConSplitterConInComponentName2 +# DRIVER_BINDING = gConSplitterSimplePointerDriverBinding +# COMPONENT_NAME = gConSplitterSimplePointerComponentName +# COMPONENT_NAME2 = gConSplitterSimplePointerComponentName2 +# DRIVER_BINDING = gConSplitterConOutDriverBinding +# COMPONENT_NAME = gConSplitterConOutComponentName +# COMPONENT_NAME2 = gConSplitterConOutComponentName2 +# DRIVER_BINDING = gConSplitterStdErrDriverBinding +# COMPONENT_NAME = gConSplitterStdErrComponentName +# COMPONENT_NAME2 = gConSplitterStdErrComponentName2 +# + +[Sources] + ConSplitterGraphics.c + ComponentName.c + ConSplitter.h + ConSplitter.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiLib + UefiDriverEntryPoint + DebugLib + PcdLib + +[Guids] + gEfiConsoleInDeviceGuid ## SOMETIMES_CONSUMES + gEfiStandardErrorDeviceGuid ## SOMETIMES_CONSUMES + gEfiConsoleOutDeviceGuid ## SOMETIMES_CONSUMES + gConnectConInEventGuid ## ALWAYS_CONSUMES + +[Protocols] + gEfiSimplePointerProtocolGuid ## BY_START + gEfiAbsolutePointerProtocolGuid ## BY_START + gEfiSimpleTextInProtocolGuid ## BY_START + gEfiSimpleTextInputExProtocolGuid ## BY_START + gEfiSimpleTextOutProtocolGuid ## BY_START + gEfiGraphicsOutputProtocolGuid ## BY_START + gEfiUgaDrawProtocolGuid ## BY_START + + +[FeaturePcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn + gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand diff --git a/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c b/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c new file mode 100644 index 0000000000..b7cdd7af39 --- /dev/null +++ b/Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c @@ -0,0 +1,628 @@ +/** @file + Support for Graphics output spliter. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include "ConSplitter.h" + + +CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL }; + +/** + Returns information for an available graphics mode that the graphics device + and the set of active video output devices supports. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. + @param Info A pointer to callee allocated buffer that returns information about ModeNumber. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + @retval EFI_OUT_OF_RESOURCES No resource available. + +**/ +EFI_STATUS +EFIAPI +ConSplitterGraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +{ + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_STATUS Status; + UINTN Index; + + if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { + return EFI_INVALID_PARAMETER; + } + + // + // retrieve private data + // + Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + GraphicsOutput = NULL; + + if (Private->CurrentNumberOfGraphicsOutput == 1) { + // + // Find the only one GraphicsOutput. + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + GraphicsOutput = Private->TextOutList[Index].GraphicsOutput; + if (GraphicsOutput != NULL) { + break; + } + } + } + + if (GraphicsOutput != NULL) { + // + // If only one physical GOP device exist, return its information. + // + Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) ModeNumber, SizeOfInfo, Info); + return Status; + } else { + // + // If 2 more phyiscal GOP device exist or GOP protocol does not exist, + // return GOP information (PixelFormat is PixelBltOnly) created in ConSplitterAddGraphicsOutputMode (). + // + *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); + if (*Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + CopyMem (*Info, &Private->GraphicsOutputModeBuffer[ModeNumber], *SizeOfInfo); + } + + return EFI_SUCCESS; +} + + +/** + Set the video device into the specified mode and clears the visible portions of + the output display to black. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber Abstraction that defines the current video mode. + + @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. + @retval EFI_OUT_OF_RESOURCES No resource available. + +**/ +EFI_STATUS +EFIAPI +ConSplitterGraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, + IN UINT32 ModeNumber + ) +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_GRAPHICS_OUTPUT_PROTOCOL *PhysicalGraphicsOutput; + UINTN NumberIndex; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + + if (ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + Mode = &Private->GraphicsOutputModeBuffer[ModeNumber]; + + ReturnStatus = EFI_SUCCESS; + GraphicsOutput = NULL; + PhysicalGraphicsOutput = NULL; + // + // return the worst status met + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + GraphicsOutput = Private->TextOutList[Index].GraphicsOutput; + if (GraphicsOutput != NULL) { + PhysicalGraphicsOutput = GraphicsOutput; + // + // Find corresponding ModeNumber of this GraphicsOutput instance + // + for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) { + Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info); + if (EFI_ERROR (Status)) { + return Status; + } + if ((Info->HorizontalResolution == Mode->HorizontalResolution) && (Info->VerticalResolution == Mode->VerticalResolution)) { + FreePool (Info); + break; + } + FreePool (Info); + } + + Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } else if (FeaturePcdGet (PcdUgaConsumeSupport)) { + UgaDraw = Private->TextOutList[Index].UgaDraw; + if (UgaDraw != NULL) { + Status = UgaDraw->SetMode ( + UgaDraw, + Mode->HorizontalResolution, + Mode->VerticalResolution, + 32, + 60 + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + } + + This->Mode->Mode = ModeNumber; + + if ((Private->CurrentNumberOfGraphicsOutput == 1) && (PhysicalGraphicsOutput != NULL)) { + // + // If only one physical GOP device exist, copy physical information to consplitter. + // + CopyMem (This->Mode->Info, PhysicalGraphicsOutput->Mode->Info, PhysicalGraphicsOutput->Mode->SizeOfInfo); + This->Mode->SizeOfInfo = PhysicalGraphicsOutput->Mode->SizeOfInfo; + This->Mode->FrameBufferBase = PhysicalGraphicsOutput->Mode->FrameBufferBase; + This->Mode->FrameBufferSize = PhysicalGraphicsOutput->Mode->FrameBufferSize; + } else { + // + // If 2 more phyiscal GOP device exist or GOP protocol does not exist, + // return GOP information (PixelFormat is PixelBltOnly) created in ConSplitterAddGraphicsOutputMode (). + // + CopyMem (This->Mode->Info, &Private->GraphicsOutputModeBuffer[ModeNumber], This->Mode->SizeOfInfo); + } + + return ReturnStatus; +} + + + +/** + The following table defines actions for BltOperations. + + EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY) + directly to every pixel of the video display rectangle + (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). + Only one pixel will be used from the BltBuffer. Delta is NOT used. + EfiBltVideoToBltBuffer - Read data from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + the BltBuffer rectangle (DestinationX, DestinationY ) + (DestinationX + Width, DestinationY + Height). If DestinationX or + DestinationY is not zero then Delta must be set to the length in bytes + of a row in the BltBuffer. + EfiBltBufferToVideo - Write data from the BltBuffer rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + not zero then Delta must be set to the length in bytes of a row in the + BltBuffer. + EfiBltVideoToVideo - Copy from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) . + to the video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). + The BltBuffer and Delta are not used in this mode. + + @param This Protocol instance pointer. + @param BltBuffer Buffer containing data to blit into video buffer. + This buffer has a size of + Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + @param BltOperation Operation to perform on BlitBuffer and video + memory + @param SourceX X coordinate of source for the BltBuffer. + @param SourceY Y coordinate of source for the BltBuffer. + @param DestinationX X coordinate of destination for the BltBuffer. + @param DestinationY Y coordinate of destination for the BltBuffer. + @param Width Width of rectangle in BltBuffer in pixels. + @param Height Hight of rectangle in BltBuffer in pixels. + @param Delta OPTIONAL. + + @retval EFI_SUCCESS The Blt operation completed. + @retval EFI_INVALID_PARAMETER BltOperation is not valid. + @retval EFI_DEVICE_ERROR A hardware error occured writting to the video + buffer. + +**/ +EFI_STATUS +EFIAPI +ConSplitterGraphicsOutputBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + + if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) { + return EFI_INVALID_PARAMETER; + } + + Private = GRAPHICS_OUTPUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + ReturnStatus = EFI_SUCCESS; + + // + // return the worst status met + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + GraphicsOutput = Private->TextOutList[Index].GraphicsOutput; + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + BltBuffer, + BltOperation, + SourceX, + SourceY, + DestinationX, + DestinationY, + Width, + Height, + Delta + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } else if (BltOperation == EfiBltVideoToBltBuffer) { + // + // Only need to read the data into buffer one time + // + return EFI_SUCCESS; + } + } + + UgaDraw = Private->TextOutList[Index].UgaDraw; + if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) { + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) BltBuffer, + (EFI_UGA_BLT_OPERATION) BltOperation, + SourceX, + SourceY, + DestinationX, + DestinationY, + Width, + Height, + Delta + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } else if (BltOperation == EfiBltVideoToBltBuffer) { + // + // Only need to read the data into buffer one time + // + return EFI_SUCCESS; + } + } + } + + return ReturnStatus; +} + +/** + Return the current video mode information. + + @param This The EFI_UGA_DRAW_PROTOCOL instance. + @param HorizontalResolution The size of video screen in pixels in the X dimension. + @param VerticalResolution The size of video screen in pixels in the Y dimension. + @param ColorDepth Number of bits per pixel, currently defined to be 32. + @param RefreshRate The refresh rate of the monitor in Hertz. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +EFI_STATUS +EFIAPI +ConSplitterUgaDrawGetMode ( + IN EFI_UGA_DRAW_PROTOCOL *This, + OUT UINT32 *HorizontalResolution, + OUT UINT32 *VerticalResolution, + OUT UINT32 *ColorDepth, + OUT UINT32 *RefreshRate + ) +{ + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + + if ((HorizontalResolution == NULL) || + (VerticalResolution == NULL) || + (RefreshRate == NULL) || + (ColorDepth == NULL)) { + return EFI_INVALID_PARAMETER; + } + // + // retrieve private data + // + Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + *HorizontalResolution = Private->UgaHorizontalResolution; + *VerticalResolution = Private->UgaVerticalResolution; + *ColorDepth = Private->UgaColorDepth; + *RefreshRate = Private->UgaRefreshRate; + + return EFI_SUCCESS; +} + + +/** + Set the current video mode information. + + @param This The EFI_UGA_DRAW_PROTOCOL instance. + @param HorizontalResolution The size of video screen in pixels in the X dimension. + @param VerticalResolution The size of video screen in pixels in the Y dimension. + @param ColorDepth Number of bits per pixel, currently defined to be 32. + @param RefreshRate The refresh rate of the monitor in Hertz. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_OUT_OF_RESOURCES Out of resources. + +**/ +EFI_STATUS +EFIAPI +ConSplitterUgaDrawSetMode ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ) +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + UINTN NumberIndex; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + + Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + ReturnStatus = EFI_SUCCESS; + + // + // Update the Mode data + // + Private->UgaHorizontalResolution = HorizontalResolution; + Private->UgaVerticalResolution = VerticalResolution; + Private->UgaColorDepth = ColorDepth; + Private->UgaRefreshRate = RefreshRate; + + // + // return the worst status met + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + + GraphicsOutput = Private->TextOutList[Index].GraphicsOutput; + if (GraphicsOutput != NULL) { + // + // Find corresponding ModeNumber of this GraphicsOutput instance + // + for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex ++) { + Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32) NumberIndex, &SizeOfInfo, &Info); + if (EFI_ERROR (Status)) { + return Status; + } + if ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution == VerticalResolution)) { + FreePool (Info); + break; + } + FreePool (Info); + } + + Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32) NumberIndex); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } else if (FeaturePcdGet (PcdUgaConsumeSupport)){ + UgaDraw = Private->TextOutList[Index].UgaDraw; + if (UgaDraw != NULL) { + Status = UgaDraw->SetMode ( + UgaDraw, + HorizontalResolution, + VerticalResolution, + ColorDepth, + RefreshRate + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + } + + return ReturnStatus; +} + + +/** + Blt a rectangle of pixels on the graphics screen. + + The following table defines actions for BltOperations. + + EfiUgaVideoFill: + Write data from the BltBuffer pixel (SourceX, SourceY) + directly to every pixel of the video display rectangle + (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). + Only one pixel will be used from the BltBuffer. Delta is NOT used. + EfiUgaVideoToBltBuffer: + Read data from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + the BltBuffer rectangle (DestinationX, DestinationY ) + (DestinationX + Width, DestinationY + Height). If DestinationX or + DestinationY is not zero then Delta must be set to the length in bytes + of a row in the BltBuffer. + EfiUgaBltBufferToVideo: + Write data from the BltBuffer rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + not zero then Delta must be set to the length in bytes of a row in the + BltBuffer. + EfiUgaVideoToVideo: + Copy from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) . + to the video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). + The BltBuffer and Delta are not used in this mode. + + @param This Protocol instance pointer. + @param BltBuffer Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL) + @param BltOperation Operation to perform on BlitBuffer and video memory + @param SourceX X coordinate of source for the BltBuffer. + @param SourceY Y coordinate of source for the BltBuffer. + @param DestinationX X coordinate of destination for the BltBuffer. + @param DestinationY Y coordinate of destination for the BltBuffer. + @param Width Width of rectangle in BltBuffer in pixels. + @param Height Hight of rectangle in BltBuffer in pixels. + @param Delta OPTIONAL + + @retval EFI_SUCCESS The Blt operation completed. + @retval EFI_INVALID_PARAMETER BltOperation is not valid. + @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer. + +**/ +EFI_STATUS +EFIAPI +ConSplitterUgaDrawBlt ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL + IN EFI_UGA_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + + Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + ReturnStatus = EFI_SUCCESS; + // + // return the worst status met + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + GraphicsOutput = Private->TextOutList[Index].GraphicsOutput; + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltBuffer, + (EFI_GRAPHICS_OUTPUT_BLT_OPERATION) BltOperation, + SourceX, + SourceY, + DestinationX, + DestinationY, + Width, + Height, + Delta + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } else if (BltOperation == EfiUgaVideoToBltBuffer) { + // + // Only need to read the data into buffer one time + // + return EFI_SUCCESS; + } + } + + if (Private->TextOutList[Index].UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) { + Status = Private->TextOutList[Index].UgaDraw->Blt ( + Private->TextOutList[Index].UgaDraw, + BltBuffer, + BltOperation, + SourceX, + SourceY, + DestinationX, + DestinationY, + Width, + Height, + Delta + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } else if (BltOperation == EfiUgaVideoToBltBuffer) { + // + // Only need to read the data into buffer one time + // + return EFI_SUCCESS; + } + } + } + + return ReturnStatus; +} + +/** + Sets the output device(s) to a specified mode. + + @param Private Text Out Splitter pointer. + @param ModeNumber The mode number to set. + +**/ +VOID +TextOutSetMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN UINTN ModeNumber + ) +{ + // + // No need to do extra check here as whether (Column, Row) is valid has + // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should + // always be supported. + // + Private->TextOutMode.Mode = (INT32) ModeNumber; + Private->TextOutMode.CursorColumn = 0; + Private->TextOutMode.CursorRow = 0; + Private->TextOutMode.CursorVisible = TRUE; + + return; +} diff --git a/Vlv2TbltDevicePkg/PciPlatform/BoardPciPlatform.c b/Vlv2TbltDevicePkg/PciPlatform/BoardPciPlatform.c new file mode 100644 index 0000000000..1f2617803e --- /dev/null +++ b/Vlv2TbltDevicePkg/PciPlatform/BoardPciPlatform.c @@ -0,0 +1,60 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + BoardPciPlatform.c + +Abstract: + +Revision History: +--*/ + + +#include "PciPlatform.h" +#include "PchRegs.h" +#include "VlvAccess.h" + +#define R_INTEL_LAN_VENDOR_ID 0x00 +#define V_INTEL_LAN_VENDOR_ID 0x8086 // INTEL 82574 Gbe Controller Vendor ID +#define R_INTEL_LAN_DEVICE_ID 0x02 +#define V_INTEL_LAN_DEVICE_ID 0x153E // INTEL 82574 Gbe Controller Device ID + +// +// Global variables for Option ROMs +// + +#define ONBOARD_VIDEO_OPTION_ROM_FILE_GUID \ +{ 0xF2FE1FAA, 0xF04A, 0x4ba1, 0xAE, 0x73, 0xD1, 0x84, 0x6A, 0x6C, 0xD6, 0xD8 } + +#define PXE_UNDI_OPTION_ROM_INTELPXE_GUID \ +{0x49F2C48B, 0x4D8E, 0x4238, 0x8D, 0x82, 0x9B, 0x27, 0xF4, 0x38, 0x44, 0xB0} + +#define SATA_AHCI_ROM_GUID \ + {0x592bfc62, 0xd817, 0x4d1a, 0x86, 0xf8, 0x33, 0x33, 0x4c, 0x9e, 0x90, 0xd8} + +#define NULL_ROM_FILE_GUID \ +{ 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + +PCI_OPTION_ROM_TABLE mPciOptionRomTable[] = { + { ONBOARD_VIDEO_OPTION_ROM_FILE_GUID, 0, 0, 0x02, 0, IGD_VID, IGD_DID_VLV_A0, 0}, + { ONBOARD_VIDEO_OPTION_ROM_FILE_GUID, 0, 0, 0x02, 0, IGD_VID, IGD_DID, 0}, // Desktop/Mobile IGD + { ONBOARD_VIDEO_OPTION_ROM_FILE_GUID, 0, 0, 0x02, 0, IGD_VID, IGD_DID_II, 0}, // Desktop/Mobile IGD + { ONBOARD_VIDEO_OPTION_ROM_FILE_GUID, 0, 0, 0x02, 0, IGD_VID, IGD_DID_QS, 0}, + { NULL_ROM_FILE_GUID, 0, 0, 0, 0, 0xffff, 0xffff, 0} +}; + +UINTN mSizeOptionRomTable = sizeof(mPciOptionRomTable)/sizeof(PCI_OPTION_ROM_TABLE); + + diff --git a/Vlv2TbltDevicePkg/PciPlatform/PciPlatform.c b/Vlv2TbltDevicePkg/PciPlatform/PciPlatform.c new file mode 100644 index 0000000000..1b59eee74f --- /dev/null +++ b/Vlv2TbltDevicePkg/PciPlatform/PciPlatform.c @@ -0,0 +1,361 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + PciPlatform.c + +Abstract: +--*/ + + +#include "PciPlatform.h" +#include "PchRegs.h" +#include "PchAccess.h" +#include "VlvCommonDefinitions.h" +#include "PlatformBootMode.h" + +#include +#include +#include +#include +#include +#include +#include "SetupMode.h" +#include +#include +#include +#include +#include +#include + +extern PCI_OPTION_ROM_TABLE mPciOptionRomTable[]; +extern UINTN mSizeOptionRomTable; + +EFI_PCI_PLATFORM_PROTOCOL mPciPlatform = { + PhaseNotify, + PlatformPrepController, + GetPlatformPolicy, + GetPciRom +}; + +EFI_HANDLE mPciPlatformHandle = NULL; + + +SYSTEM_CONFIGURATION mSystemConfiguration; + +EFI_STATUS +GetRawImage ( + IN EFI_GUID *NameGuid, + IN OUT VOID **Buffer, + IN OUT UINTN *Size + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; + UINT32 AuthenticationStatus; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status) || HandleCount == 0) { + return EFI_NOT_FOUND; + } + + // + // Find desired image in all Fvs + // + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol( + HandleBuffer[Index], + &gEfiFirmwareVolumeProtocolGuid, + (VOID **) &Fv + ); + + if ( EFI_ERROR ( Status ) ) { + return EFI_LOAD_ERROR; + } + + // + // Try a raw file + // + *Buffer = NULL; + *Size = 0; + Status = Fv->ReadSection ( + Fv, + NameGuid, + EFI_SECTION_RAW, + 0, + Buffer, + Size, + &AuthenticationStatus + ); + + if ( !EFI_ERROR ( Status )) { + break; + } + } + + if ( Index >= HandleCount ) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +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 + ) +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +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 +EFIAPI +GetPlatformPolicy ( + IN CONST EFI_PCI_PLATFORM_PROTOCOL *This, + OUT EFI_PCI_PLATFORM_POLICY *PciPolicy + ) +{ + *PciPolicy = EFI_RESERVE_VGA_IO_ALIAS; + return EFI_SUCCESS; +} + +/** + GetPciRom from platform specific location for specific PCI device + + @param This Protocol instance + @param PciHandle Identify the specific PCI devic + @param RomImage Returns the ROM Image memory location + @param RomSize Returns Rom Image size + + @retval EFI_SUCCESS + @retval EFI_NOT_FOUND + @retval EFI_OUT_OF_RESOURCES + +**/ +EFI_STATUS +EFIAPI +GetPciRom ( + IN CONST EFI_PCI_PLATFORM_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, + OUT UINTN *RomSize + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + UINT16 VendorId; + UINT16 DeviceId; + UINT16 DeviceClass; + UINTN TableIndex; + UINT8 Data8; + BOOLEAN MfgMode; + EFI_PLATFORM_SETUP_ID *BootModeBuffer; + + EFI_PEI_HOB_POINTERS GuidHob; + + MfgMode = FALSE; + +// +// Check if system is in manufacturing mode. +// + GuidHob.Raw = GetHobList (); + if (GuidHob.Raw == NULL) { + return EFI_NOT_FOUND; + } + + if ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformBootModeGuid, GuidHob.Raw)) != NULL) { + BootModeBuffer = GET_GUID_HOB_DATA (GuidHob.Guid); + if (!CompareMem (&BootModeBuffer->SetupName, MANUFACTURE_SETUP_NAME, + StrSize (MANUFACTURE_SETUP_NAME))) + { + // + // System is in manufacturing mode. + // + MfgMode = TRUE; + } + } + + Status = gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (void **)&PciIo + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + Status = gBS->LocateProtocol ( + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + (void **)&PciRootBridgeIo + ); + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0x0A, 1, &DeviceClass); + + PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); + + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0, 1, &VendorId); + + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 2, 1, &DeviceId); + + // + // WA for PCIe SATA card (SYBA SY-PEX400-40) + // + if ((VendorId == 0x1B21) && (DeviceId == 0x0612)) { + Data8 = 0x07; + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 4, 1, &Data8); + } + + // + // Do not run RAID or AHCI Option ROM if IDE + // + if ( (DeviceClass == ((PCI_CLASS_MASS_STORAGE << 8 ) | PCI_CLASS_MASS_STORAGE_IDE)) ) { + return EFI_NOT_FOUND; + } + + // + // Run PXE ROM only if Boot network is enabled and not in MFG mode + // + if (DeviceClass == ((PCI_CLASS_NETWORK << 8 ) | PCI_CLASS_NETWORK_ETHERNET)) { + if (((mSystemConfiguration.BootNetwork == 0) && (MfgMode == FALSE )) || (mSystemConfiguration.FastBoot == 1)) { + return EFI_NOT_FOUND; + } + } + + // + // Loop through table of Onboard 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 || + ((DeviceClass == ((PCI_CLASS_NETWORK << 8 ) | PCI_CLASS_NETWORK_ETHERNET)) && + (mPciOptionRomTable[TableIndex].Flag != mSystemConfiguration.BootNetwork)) ) { + continue; + } + + Status = GetRawImage( + &mPciOptionRomTable[TableIndex].FileName, + RomImage, + RomSize + ); + + if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_VLV_A0)) { + *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_VLV_A0; + } + + if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_II)) { + *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_II; + } + + if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_0BE4)) { + *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_0BE4; + } + + if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_QS)) { + *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_QS; + } + + + if (EFI_ERROR (Status)) { + continue; + } + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +/** + + @param (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + + @retval EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +PciPlatformDriverEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINTN VarSize; + + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + L"Setup", + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &mSystemConfiguration + ); + ASSERT_EFI_ERROR(Status); + + // + // Install on a new handle + // + Status = gBS->InstallProtocolInterface ( + &mPciPlatformHandle, + &gEfiPciPlatformProtocolGuid, + EFI_NATIVE_INTERFACE, + &mPciPlatform + ); + + return Status; +} + + diff --git a/Vlv2TbltDevicePkg/PciPlatform/PciPlatform.h b/Vlv2TbltDevicePkg/PciPlatform/PciPlatform.h new file mode 100644 index 0000000000..75076449a3 --- /dev/null +++ b/Vlv2TbltDevicePkg/PciPlatform/PciPlatform.h @@ -0,0 +1,88 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + PciPlatform.h + +Abstract: + +--*/ +#ifndef PCI_PLATFORM_H_ +#define PCI_PLATFORM_H_ + + +#include +#include "Platform.h" + +// +// Produced Protocols +// +#include + +#define IGD_DID_II 0x0BE1 +#define IGD_DID_0BE4 0x0BE4 +#define IGD_DID_VLV_A0 0x0F31 +#define OPROM_DID_OFFSET 0x46 + +typedef struct { + EFI_GUID FileName; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + UINT16 VendorId; + UINT16 DeviceId; + UINT8 Flag; +} PCI_OPTION_ROM_TABLE; + +EFI_STATUS +EFIAPI +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 +EFIAPI +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 +EFIAPI +GetPlatformPolicy ( + IN CONST EFI_PCI_PLATFORM_PROTOCOL *This, + OUT EFI_PCI_PLATFORM_POLICY *PciPolicy + ); + +EFI_STATUS +EFIAPI +GetPciRom ( + IN CONST EFI_PCI_PLATFORM_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, + OUT UINTN *RomSize + ); + +#endif + + diff --git a/Vlv2TbltDevicePkg/PciPlatform/PciPlatform.inf b/Vlv2TbltDevicePkg/PciPlatform/PciPlatform.inf new file mode 100644 index 0000000000..a296c24b75 --- /dev/null +++ b/Vlv2TbltDevicePkg/PciPlatform/PciPlatform.inf @@ -0,0 +1,70 @@ +#/*++ +# +# Copyright (c) 2003 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +# +# Module Name: +# +# PciPlatform.inf +# +# Abstract: +# +# Component description file for PciPlatform module. +# +--*/ + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = PciPlatform + FILE_GUID = E2441B64-7EF4-41fe-B3A3-8CAA7F8D3017 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PciPlatformDriverEntry + +[sources.common] + BoardPciPlatform.c + PciPlatform.c + PciPlatform.h + +[Guids] + gEfiNormalSetupGuid + gEfiPlatformBootModeGuid + +[Protocols] + gEfiPciPlatformProtocolGuid + gEfiCpuIoProtocolGuid + gEfiFirmwareVolumeProtocolGuid + gEfiPciRootBridgeIoProtocolGuid + gEfiPciIoProtocolGuid + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +[LibraryClasses] + HobLib + UefiDriverEntryPoint + BaseLib + BaseMemoryLib + UefiDriverEntryPoint + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DxeServicesTableLib + +[BuildOptions] + +[Depex] + gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid diff --git a/Vlv2TbltDevicePkg/PlatformCpuInfoDxe/PlatformCpuInfoDxe.c b/Vlv2TbltDevicePkg/PlatformCpuInfoDxe/PlatformCpuInfoDxe.c new file mode 100644 index 0000000000..bd46a13aba --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformCpuInfoDxe/PlatformCpuInfoDxe.c @@ -0,0 +1,65 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + PlatformCpuInfoDxe.c + +Abstract: + Platform Cpu Info driver to public platform related HOB data + +--*/ + +#include "PlatformCpuInfoDxe.h" + +CHAR16 EfiPlatformCpuInfoVariable[] = L"PlatformCpuInfo"; + +EFI_STATUS +EFIAPI +PlatformCpuInfoInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_PLATFORM_CPU_INFO *PlatformCpuInfoPtr; + EFI_PEI_HOB_POINTERS GuidHob; + + // + // Get Platform Cpu Info HOB + // + GuidHob.Raw = GetHobList (); + while ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformCpuInfoGuid, GuidHob.Raw)) != NULL) { + PlatformCpuInfoPtr = GET_GUID_HOB_DATA (GuidHob.Guid); + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + + // + // Write the Platform CPU Info to volatile memory for runtime purposes. + // This must be done in its own driver because SetVariable protocol is dependent on chipset, + // which is dependent on CpuIo, PlatformInfo, and Metronome. + // + Status = gRT->SetVariable( + EfiPlatformCpuInfoVariable, + &gEfiVlv2VariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(EFI_PLATFORM_CPU_INFO), + PlatformCpuInfoPtr + ); + if (EFI_ERROR(Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/PlatformCpuInfoDxe/PlatformCpuInfoDxe.h b/Vlv2TbltDevicePkg/PlatformCpuInfoDxe/PlatformCpuInfoDxe.h new file mode 100644 index 0000000000..3d8803adc2 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformCpuInfoDxe/PlatformCpuInfoDxe.h @@ -0,0 +1,34 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + PlatformCpuInfoDxe.h + +Abstract: + Platform Cpu Info Driver. + +--*/ + +#ifndef _PLATFORM_CPU_INFO_DRIVER_H_ +#define _PLATFORM_CPU_INFO_DRIVER_H_ + +#include "PiDxe.h" +#include "Library/HobLib.h" +#include "Guid/GlobalVariable.h" +#include "Guid/AcpiVariableCompatibility.h" +#include "Guid/PlatformCpuInfo.h" +#include "Library/UefiRuntimeServicesTableLib.h" +#include + +#endif diff --git a/Vlv2TbltDevicePkg/PlatformCpuInfoDxe/PlatformCpuInfoDxe.inf b/Vlv2TbltDevicePkg/PlatformCpuInfoDxe/PlatformCpuInfoDxe.inf new file mode 100644 index 0000000000..a0e99fb152 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformCpuInfoDxe/PlatformCpuInfoDxe.inf @@ -0,0 +1,61 @@ +#/*++ +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +# +# Module Name: +# +# PlatformCpuInfoDxe.inf +# +# Abstract: +# +# +--*/ + + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformCpuInfoDxe + FILE_GUID = 025F738B-4EBD-4d55-B728-5F421B601F20 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PlatformCpuInfoInit + +[Sources] + PlatformCpuInfoDxe.c + PlatformCpuInfoDxe.h + +[Guids] + gEfiPlatformCpuInfoGuid + gEfiVlv2VariableGuid + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + IA32FamilyCpuPkg/IA32FamilyCpuPkg.dec #CpuConfigLib.h + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + HobLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + +[BuildOptions] + MSFT:*_*_*_CC_FLAGS = /Od /GL- + INTEL:*_*_*_CC_FLAGS = /Od /GL- + +[Depex] + gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid + diff --git a/Vlv2TbltDevicePkg/PlatformDxe/AzaliaVerbTable.h b/Vlv2TbltDevicePkg/PlatformDxe/AzaliaVerbTable.h new file mode 100644 index 0000000000..47a2d1a293 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/AzaliaVerbTable.h @@ -0,0 +1,252 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +--*/ + +UINT32 mAzaliaVerbTableData12[] = { + // + // Audio Verb Table - 0x80862805 + // + // Pin Widget 5 - PORT B + 0x20471C10, + 0x20471D00, + 0x20471E56, + 0x20471F18, + + // Pin Widget 6 - PORT C + 0x20571C20, + 0x20571D00, + 0x20571E56, + 0x20571F18, + + // Pin Widget 7 - PORT D + 0x20671C30, + 0x20671D00, + 0x20671E56, + 0x20671F58 +}; + + +PCH_AZALIA_VERB_TABLE mAzaliaVerbTable[] = { + { + // + // VerbTable: + // Revision ID = 0xFF, support all steps + // Codec Verb Table For AZALIA + // Codec Address: CAd value (0/1/2) + // Codec Vendor: 0x10EC0880 + // + { + 0x10EC0880, // Vendor ID/Device ID + 0x0000, // SubSystem ID + 0xFF, // Revision ID + 0x01, // Front panel support (1=yes, 2=no) + 0x000A, // Number of Rear Jacks = 10 + 0x0002 // Number of Front Jacks = 2 + }, + 0 // Pointer to verb table data, need to be inited in the code. + }, + { + // + // Revision ID >= 0x03 + // Codec Verb Table For AZALIA + // Codec Address: CAd value (0/1/2) + // Codec Vendor: 0x434D4980 + // + { + 0x434D4980, // Vendor ID/Device ID + 0x0000, // SubSystem ID + 0x00, // Revision ID + 0x01, // Front panel support (1=yes, 2=no) + 0x0009, // Number of Rear Jacks = 9 + 0x0002 // Number of Front Jacks = 2 + }, + 0 // Pointer to verb table data, need to be inited in the code. + }, + { + // + // Lawndale Azalia Audio Codec Verb Table + // Revision ID = 0x00 + // Codec Address: CAd value (0/1/2) + // Codec Vendor: 0x11D41984 + // + { + 0x11D41984, // Vendor ID/Device ID + 0x0000, // SubSystem ID + 0x04, // Revision ID + 0x01, // Front panel support (1=yes, 2=no) + 0x0009, // Number of Rear Jacks = 9 + 0x0002 // Number of Front Jacks = 2 + }, + 0 // Pointer to verb table data, need to be inited in the code. + }, + { + // + // VerbTable: + // Revision ID = 0xFF, support all steps + // Codec Verb Table For AZALIA + // Codec Address: CAd value (0/1/2) + // Codec Vendor: 0x11D41986 + // + { + 0x11D41986, // Vendor ID/Device ID + 0x0001, // SubSystem ID + 0xFF, // Revision ID + 0x01, // Front panel support (1=yes, 2=no) + 0x000A, // Number of Rear Jacks = 8 + 0x0002 // Number of Front Jacks = 2 + }, + 0 // Pointer to verb table data, need to be inited in the code. + }, + { + // + // VerbTable: (for Slim River, FFDS3) + // Revision ID = 0x00 + // Codec Verb Table For AZALIA + // Codec Address: CAd value (0/1/2) + // Codec Vendor: 0x10EC0272 + // + { + 0x10EC0272, // Vendor ID/Device ID + 0x0000, // SubSystem ID + 0x00, // Revision ID + 0x01, // Front panel support (1=yes, 2=no) + 0x000E, // Number of Rear Jacks + 0x0002 // Number of Front Jacks + }, + 0 // Pointer to verb table data, need to be inited in the code. + }, + { + // + // VerbTable: (for Buffalo Trail) + // Revision ID = 0x00 + // Codec Verb Table For AZALIA + // Codec Address: CAd value (0/1/2) + // Codec Vendor: 0x10EC0269 + // + { + 0x10EC0269, // Vendor ID/Device ID + 0x0000, // SubSystem ID + 0x00, // Revision ID + 0x01, // Front panel support (1=yes, 2=no) + 0x000A, // Number of Rear Jacks + 0x0002 // Number of Front Jacks + }, + 0 // Pointer to verb table data, need to be inited in the code. + }, + { + // + // VerbTable: (RealTek ALC888) + // Revision ID = 0xFF + // Codec Verb Table For Redfort + // Codec Address: CAd value (0/1/2) + // Codec Vendor: 0x10EC0888 + // + { + 0x10EC0888, // Vendor ID/Device ID + 0x0000, // SubSystem ID + 0xFF, // Revision ID + 0x01, // Front panel support (1=yes, 2=no) + 0x000B, // Number of Rear Jacks + 0x0002 // Number of Front Jacks + }, + 0 // Pointer to verb table data, need to be inited in the code. + }, + { + // + // VerbTable: (RealTek ALC885) + // Revision ID = 0xFF + // Codec Verb Table For Redfort + // Codec Address: CAd value (0/1/2) + // Codec Vendor: 0x10EC0885 + // + { + 0x10EC0885, // Vendor ID/Device ID + 0x0000, // SubSystem ID + 0xFF, // Revision ID + 0x01, // Front panel support (1=yes, 2=no) + 0x000B, // Number of Rear Jacks + 0x0002 // Number of Front Jacks + }, + 0 // Pointer to verb table data, need to be inited in the code. + }, + { + // + // VerbTable: (IDT 92HD81) + // Revision ID = 0xFF + // Codec Vendor: 0x111D7605 + // + { + 0x111D76d5, // Vendor ID/Device ID + 0x0000, // SubSystem ID + 0xFF, // Revision ID + 0x01, // Front panel support (1=yes, 2=no) + 0x0008, // Number of Rear Jacks + 0x0002 // Number of Front Jacks + }, + 0 // Pointer to verb table data, need to be inited in the code. + }, + { + // + // VerbTable: (Intel VLV HDMI) + // Revision ID = 0xFF + // Codec Verb Table For EmeraldLake/LosLunas + // Codec Vendor: 0x80862804 + // + { + 0x80862882, // Vendor ID/Device ID + 0x0000, // SubSystem ID + 0xFF, // Revision ID + 0x02, // Front panel support (1=yes, 2=no) + 0x0003, // Number of Rear Jacks + 0x0000 // Number of Front Jacks + }, + 0 // Pointer to verb table data, need to be inited in the code. + }, + { + // + // VerbTable: (RealTek ALC262) + // Revision ID = 0xFF, support all steps + // Codec Verb Table For AZALIA + // Codec Address: CAd value (0/1/2) + // Codec Vendor: 0x10EC0262 + // + { + 0x10EC0262, // Vendor ID/Device ID + 0x0000, // SubSystem ID + 0xFF, // Revision ID + 0x01, // Front panel support (1=yes, 2=no) + 0x000B, // Number of Rear Jacks = 11 + 0x0002 // Number of Front Jacks = 2 + }, + 0 // Pointer to verb table data, need to be inited in the code. + }, + { + // + // VerbTable: (RealTek ALC282) + // Revision ID = 0xff + // Codec Verb Table For Azalia on SharkBay-WhiteBluff refresh and Haswell ULT FFRD Harris Beach, WTM1, WTM2iCRB + // Codec Address: CAd value (0/1/2) + // Codec Vendor: 0x10EC0282 + // + { + 0x10EC0282, // Vendor ID/Device ID + 0x0000, // SubSystem ID + 0xff, // Revision ID + 0x01, // Front panel support (1=yes, 2=no) + 0x000C, // Number of Rear Jacks, 0x0010 for Harris Beach, 0x000B for WTM1 & WTM2iCRB + 0x0002 // Number of Front Jacks + }, + 0 // Pointer to verb table data, need to be inited in the code. + } +}; diff --git a/Vlv2TbltDevicePkg/PlatformDxe/BoardId.c b/Vlv2TbltDevicePkg/PlatformDxe/BoardId.c new file mode 100644 index 0000000000..5b6139b2d6 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/BoardId.c @@ -0,0 +1,228 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + BoardId.c + +Abstract: + + Initialization for the board ID. + + This code should be common across a chipset family of products. + + + +--*/ + +#include "PchRegs.h" +#include "PlatformDxe.h" +#include +#include +#include + + +extern EFI_GUID mPlatformDriverGuid; + +// +// Global module data +// +UINT32 mBoardId; +UINT8 mBoardIdIndex; +EFI_BOARD_FEATURES mBoardFeatures; +UINT16 mSubsystemDeviceId; +UINT16 mSubsystemAudioDeviceId; +CHAR8 BoardAaNumber[7]; +BOOLEAN mFoundAANum; + +/** + + Write the boardid variable if it does not already exist. + +**/ +VOID +InitializeBoardId ( + ) +{ + + UINT32 BoardIdBufferSize; + EFI_IDCC_BOARD_FORM_FACTOR IdccBoardFormFactor; + EFI_DATA_HUB_PROTOCOL *DataHub; + EFI_STATUS Status; + DMI_DATA DmiDataVariable; + UINTN Size; +#if defined(DUPLICATE_AA_NO_BASE_ADDR) + CHAR8 DuplicateAaNoAscii[sizeof(DmiDataVariable.BaseBoardVersion)]; + UINTN iter; +#endif +#if defined(GPIO_BOARD_ID_SUPPORT) && GPIO_BOARD_ID_SUPPORT != 0 + UINT8 Data8; +#endif + + // + // Update data from the updatable DMI data area + // + Size = sizeof (DMI_DATA); + SetMem(&DmiDataVariable, Size, 0xFF); + Status = gRT->GetVariable ( + DMI_DATA_NAME, + &gDmiDataGuid, + NULL, + &Size, + &DmiDataVariable + ); + +#if defined(DUPLICATE_AA_NO_BASE_ADDR) + // + // Get AA# from flash descriptor region + // + EfiSetMem(DuplicateAaNoAscii, sizeof(DuplicateAaNoAscii), 0xFF); + FlashRead((UINT8 *)(UINTN)DUPLICATE_AA_NO_BASE_ADDR, + (UINT8 *)DuplicateAaNoAscii, + sizeof(DuplicateAaNoAscii)); + + // + // Validate AA# read from VPD + // + for (iter = 0; iter < sizeof(DuplicateAaNoAscii); iter++) { + if ((DuplicateAaNoAscii[iter] != 0xFF) && + (DuplicateAaNoAscii[iter] != DmiDataVariable.BaseBoardVersion[iter])) { + DmiDataVariable.BaseBoardVersion[iter] = DuplicateAaNoAscii[iter]; + } + } + + Status = EFI_SUCCESS; +#endif + + mFoundAANum = FALSE; + + // + // No variable...no copy + // + if (EFI_ERROR (Status)) { + mBoardIdIndex = 0; // If we can't find the BoardId in the table, use the first entry + } else { + // + // This is the correct method of checking for AA#. + // + CopyMem(&BoardAaNumber, ((((UINT8*)&DmiDataVariable.BaseBoardVersion)+2)), 6); + BoardAaNumber[6] = 0; + for (mBoardIdIndex = 0; mBoardIdIndex < mBoardIdDecodeTableSize; mBoardIdIndex++) { + if (AsciiStrnCmp(mBoardIdDecodeTable[mBoardIdIndex].AaNumber, BoardAaNumber, 6) == 0) { + mFoundAANum = TRUE; + break; + } + } + + if(!mFoundAANum) { + // + // Add check for AA#'s that is programmed without the AA as leading chars. + // + CopyMem(&BoardAaNumber, (((UINT8*)&DmiDataVariable.BaseBoardVersion)), 6); + BoardAaNumber[6] = 0; + for (mBoardIdIndex = 0; mBoardIdIndex < mBoardIdDecodeTableSize; mBoardIdIndex++) { + if (AsciiStrnCmp(mBoardIdDecodeTable[mBoardIdIndex].AaNumber, BoardAaNumber, 6) == 0) { + mFoundAANum = TRUE; + break; + } + } + } + } + +#if defined(GPIO_BOARD_ID_SUPPORT) && GPIO_BOARD_ID_SUPPORT != 0 + // + // If we can't find the BoardAA# in the table, find BoardId + // + if (mFoundAANum != TRUE) { + // + // BoardID BIT Location + // 0 GPIO33 (ICH) + // 1 GPIO34 (ICH) + // + Data8 = IoRead8(GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL2); + + // + // BoardId[0] + // + mBoardId = (UINT32)((Data8 >> 1) & BIT0); + // + // BoardId[1] + // + mBoardId |= (UINT32)((Data8 >> 1) & BIT1); + + for (mBoardIdIndex = 0; mBoardIdIndex < mBoardIdDecodeTableSize; mBoardIdIndex++) { + if (mBoardIdDecodeTable[mBoardIdIndex].BoardId == mBoardId) { + break; + } + } +#endif + if (mBoardIdIndex == mBoardIdDecodeTableSize) { + mBoardIdIndex = 0; // If we can't find the BoardId in the table, use the first entry + } +#if defined(GPIO_BOARD_ID_SUPPORT) && GPIO_BOARD_ID_SUPPORT != 0 + } +#endif + + mBoardFeatures = mBoardIdDecodeTable[mBoardIdIndex].Features; + mSubsystemDeviceId = mBoardIdDecodeTable[mBoardIdIndex].SubsystemDeviceId; + mSubsystemAudioDeviceId = mBoardIdDecodeTable[mBoardIdIndex].AudioSubsystemDeviceId; + + // + // Set the BoardFeatures variable + // + BoardIdBufferSize = sizeof (mBoardFeatures); + gRT->SetVariable ( + BOARD_FEATURES_NAME, + &gEfiBoardFeaturesGuid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + BoardIdBufferSize, + &mBoardFeatures + ); + + // + // Get the Data Hub protocol + // + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + (VOID **) &DataHub + ); + if (!(EFI_ERROR(Status))) { + // + // Fill out data + // + IdccBoardFormFactor.IdccHeader.Type = EFI_IDCC_BOARD_FORM_FACTOR_TYPE; + IdccBoardFormFactor.IdccHeader.RecordLength = sizeof(EFI_IDCC_BOARD_FORM_FACTOR); + if ((mBoardFeatures & B_BOARD_FEATURES_FORM_FACTOR_ATX) || (mBoardFeatures & B_BOARD_FEATURES_FORM_FACTOR_MICRO_ATX)) { + IdccBoardFormFactor.BoardFormFactor = ATX_FORM_FACTOR; // ATX + } else { + IdccBoardFormFactor.BoardFormFactor = BTX_FORM_FACTOR; // BTX + } + + // + // Publish the Board Form Factor value for IDCC + // + Status = DataHub->LogData ( + DataHub, + &gIdccDataHubGuid, + &mPlatformDriverGuid, + EFI_DATA_RECORD_CLASS_DATA, + &IdccBoardFormFactor, + sizeof(EFI_IDCC_BOARD_FORM_FACTOR) + ); + } +} + diff --git a/Vlv2TbltDevicePkg/PlatformDxe/BoardIdDecode.c b/Vlv2TbltDevicePkg/PlatformDxe/BoardIdDecode.c new file mode 100644 index 0000000000..cf9b904b2c --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/BoardIdDecode.c @@ -0,0 +1,134 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + BoardIdDecode.c + +Abstract: + +--*/ + +#include "PchRegs.h" +#include "PlatformDxe.h" +#include "Platform.h" + + +// +// Define macros to build data structure signatures from characters. +// +#define EFI_SIGNATURE_16(A, B) ((A) | (B << 8)) +#define EFI_SIGNATURE_32(A, B, C, D) (EFI_SIGNATURE_16 (A, B) | (EFI_SIGNATURE_16 (C, D) << 16)) +#define EFI_SIGNATURE_64(A, B, C, D, E, F, G, H) \ + (EFI_SIGNATURE_32 (A, B, C, D) | ((UINT64) (EFI_SIGNATURE_32 (E, F, G, H)) << 32)) + +BOARD_ID_DECODE mBoardIdDecodeTable[] = { + // + // Board ID, Board Features bitmap, Subsystem Device ID + // This is a dummy entry that has to exist. Do not delete, just make a generic entry that fit for product. + // + { + MW_ITX_MPCIE_LVDS_LOEM_AA, + MW_ITX_MPCIE_LVDS_LOEM_ID, + B_BOARD_FEATURES_FORM_FACTOR_ATX | + B_BOARD_FEATURES_SIO_COM2 | + B_BOARD_FEATURES_2_C0_MEMORY_SLOT | + V_BOARD_FEATURES_SLEEP_S3 | + B_BOARD_FEATURES_PS2WAKEFROMS5 | + B_BOARD_FEATURES_LVDS | + B_BOARD_FEATURES_VERB_TABLE1, + V_DEFAULT_SUBSYSTEM_DEVICE_ID, + 0xD625, + EFI_SIGNATURE_64('M','W','P','N','T','1','0','N') + }, + + { + MW_ITX_MPCIE_LVDS_CHANNEL_AA, + MW_ITX_MPCIE_LVDS_CHANNEL_ID, + B_BOARD_FEATURES_FORM_FACTOR_ATX | + B_BOARD_FEATURES_SIO_COM2 | + B_BOARD_FEATURES_2_C0_MEMORY_SLOT | + V_BOARD_FEATURES_SLEEP_S3 | + B_BOARD_FEATURES_PS2WAKEFROMS5 | + B_BOARD_FEATURES_LVDS | + B_BOARD_FEATURES_VERB_TABLE1, + V_DEFAULT_SUBSYSTEM_DEVICE_ID, + 0xD625, + EFI_SIGNATURE_64('M','W','P','N','T','1','0','N') + }, + + { + MW_ITX_MPCIE_CHANNEL_AA, + MW_ITX_MPCIE_CHANNEL_ID, + B_BOARD_FEATURES_FORM_FACTOR_ATX | + B_BOARD_FEATURES_SIO_COM2 | + B_BOARD_FEATURES_2_C0_MEMORY_SLOT | + V_BOARD_FEATURES_SLEEP_S3 | + B_BOARD_FEATURES_PS2WAKEFROMS5 | + B_BOARD_FEATURES_VERB_TABLE1, + V_DEFAULT_SUBSYSTEM_DEVICE_ID, + 0xD625, + EFI_SIGNATURE_64('M','W','P','N','T','1','0','N') + }, + + { + KT_ITX_MPCIE_LVDS_LOEM_AA, + KT_ITX_MPCIE_LVDS_LOEM_ID, + B_BOARD_FEATURES_FORM_FACTOR_ATX | + B_BOARD_FEATURES_SIO_COM2 | + B_BOARD_FEATURES_2_C0_MEMORY_SLOT | + V_BOARD_FEATURES_SLEEP_S3 | + B_BOARD_FEATURES_PS2WAKEFROMS5 | + B_BOARD_FEATURES_LVDS | + B_BOARD_FEATURES_VERB_TABLE2, + V_DEFAULT_SUBSYSTEM_DEVICE_ID_KT, + 0xD626, + EFI_SIGNATURE_64('K','T','P','N','T','1','0','N') + }, + + { + KT_ITX_CHANNEL_AA, + KT_ITX_CHANNEL_ID, + B_BOARD_FEATURES_FORM_FACTOR_ATX | + B_BOARD_FEATURES_SIO_COM2 | + B_BOARD_FEATURES_2_C0_MEMORY_SLOT | + V_BOARD_FEATURES_SLEEP_S3 | + B_BOARD_FEATURES_PS2WAKEFROMS5 | + B_BOARD_FEATURES_NO_MINIPCIE | + B_BOARD_FEATURES_VERB_TABLE2, + V_DEFAULT_SUBSYSTEM_DEVICE_ID_KT, + 0xD626, + EFI_SIGNATURE_64('K','T','P','N','T','1','0','N') + }, + + { + KT_ITX_LOEM_AA, + KT_ITX_LOEM_ID, + B_BOARD_FEATURES_FORM_FACTOR_ATX | + B_BOARD_FEATURES_SIO_COM2 | + B_BOARD_FEATURES_2_C0_MEMORY_SLOT | + V_BOARD_FEATURES_SLEEP_S3 | + B_BOARD_FEATURES_PS2WAKEFROMS5 | + B_BOARD_FEATURES_NO_MINIPCIE | + B_BOARD_FEATURES_VERB_TABLE2, + V_DEFAULT_SUBSYSTEM_DEVICE_ID_KT, + 0xD626, + EFI_SIGNATURE_64('K','T','P','N','T','1','0','N') + } +}; + +UINTN mBoardIdDecodeTableSize = sizeof (mBoardIdDecodeTable) / + sizeof (mBoardIdDecodeTable[0]); + + diff --git a/Vlv2TbltDevicePkg/PlatformDxe/BoardIdDecode.h b/Vlv2TbltDevicePkg/PlatformDxe/BoardIdDecode.h new file mode 100644 index 0000000000..8240cd87cc --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/BoardIdDecode.h @@ -0,0 +1,66 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + BoardIdDecode.h + +Abstract: + + Header file for Platform Initialization Driver. + +Revision History + +++*/ + +// +// Board AA# and Board ID +// +#define DEFAULT_BOARD_AA "FFFFFF" + +// +// Mount Washington (LVDS) LOEM +// +#define MW_ITX_MPCIE_LVDS_LOEM_AA "E93081" +#define MW_ITX_MPCIE_LVDS_LOEM_ID 3 + +// +// Mount Washington (LVDS) Channel +// +#define MW_ITX_MPCIE_LVDS_CHANNEL_AA "E93080" +#define MW_ITX_MPCIE_LVDS_CHANNEL_ID 3 + +// +// Mount Washington Channel +// +#define MW_ITX_MPCIE_CHANNEL_AA "E93082" +#define MW_ITX_MPCIE_CHANNEL_ID 1 + +// +// Kinston (mPCIe + LVDS) LOEM +// +#define KT_ITX_MPCIE_LVDS_LOEM_AA "E93085" +#define KT_ITX_MPCIE_LVDS_LOEM_ID 2 + +// +// Kinston (LVDS) Channel +// +#define KT_ITX_CHANNEL_AA "E93083" +#define KT_ITX_CHANNEL_ID 0 + +// +// Kinston LOEM +// +#define KT_ITX_LOEM_AA "E93084" +#define KT_ITX_LOEM_ID 0 + diff --git a/Vlv2TbltDevicePkg/PlatformDxe/ClockControl.c b/Vlv2TbltDevicePkg/PlatformDxe/ClockControl.c new file mode 100644 index 0000000000..cc6ca3c44a --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/ClockControl.c @@ -0,0 +1,207 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + ClockControl.c + +Abstract: + + Sets platform/SKU specific clock routing information. + + + +--*/ + +#include "PlatformDxe.h" +#include + +// +// Default clock routing informtion (All On) +// +EFI_CLOCK_PLATFORM_INFO mDefClockPolicy = {NULL, 0, NULL, 0, NULL, 0}; + +// +// Clock Settings +// +// Static clock table. +// This should be used to define any clock settings that are static +// (Always On or Always Off). Dynamic clocks should be set to enabled +// in this table. +// +EFI_STATIC_SIGNALS mAtxStaticClocks[] = { + {SrcClk8, Enabled, All}, + {SrcClk7, Enabled, All}, + {SrcClk6, Enabled, All}, + {SrcClk5, Enabled, All}, + {SrcClk4, Enabled, All}, + {SrcClk3, Enabled, All}, + {SrcClk2, Enabled, All}, + {SrcClk1, Enabled, All}, + {SrcClk0, Enabled, All}, + {Ref0, Enabled, All}, + {Dot96, Enabled, All}, + {Usb48, Enabled, All}, + {PciClkF5, Enabled, All}, + {PciClk0, Enabled, All}, + {PciClk2, Enabled, All}, + {PciClk3, Enabled, All}, + {PciClk4, Disabled, All}, + {Cr_B, EnabledWithSwitch, All}, +}; + +// +// ClockSxInfo Table +// This is a list of clocks that need to be set to a known state when the +// system enters S4 or S5. +// +EFI_STATIC_SIGNALS mAtxSxClocks[] = { + {SaveClockConfiguration, Disabled, All} +}; + +// +// ATX settings structure +// +EFI_CLOCK_PLATFORM_INFO mAtxClockSettings = { + mAtxStaticClocks, + sizeof(mAtxStaticClocks) / sizeof(mAtxStaticClocks[0]), + mAtxSxClocks, + sizeof(mAtxSxClocks) / sizeof(mAtxSxClocks[0]) +}; + +#if defined( RVP_SUPPORT ) && RVP_SUPPORT +// +// RVP Clock Settings +// +// Static clock table. +// This should be used to define any clock settings that are static +// (Always On or Always Off). Dynamic clocks should be set to enabled +// in this table. +// +//UPSD_TBD Check with Jan if any porting required. +// +EFI_STATIC_SIGNALS mRvpStaticClocks[] = { + {SrcClk11, Enabled, All}, // Not used/not present but leave coding enabled + {SrcClk10, Enabled, All}, // Not used/not present but leave coding enabled + {SrcClk9, Enabled, All}, // Not used/not present but leave coding enabled + {SrcClk8, Enabled, All}, // ICHSATAII + {SrcClk7, Enabled, All}, // DPL_REFSSCLKIN + {SrcClk6, Enabled, All}, // 100M_MCH + {SrcClk5, Enabled, All}, // Mini-PCIe //TODO PNV: Need to check ICH GPIO38: + // 0: turn on; 1: turn off + {SrcClk4, Enabled, All}, // ICHSATA + {SrcClk3, Enabled, All}, // 100M_ICH + {SrcClk2, Enabled, All}, // 100M_LAN + {SrcClk1, Enabled, All}, // 25M_LAN + {SrcClk0, Enabled, All}, // 96M_DREF + {Ref0, Enabled, All}, + {Dot96, Enabled, All}, + {Usb48, Enabled, All}, + {PciClkF5, Enabled, All}, // 33M_ICH + {PciClk0, Enabled, All}, // 33M_RISER + {PciClk1, Enabled, All}, // 33M_RISER + {PciClk2, Enabled, All}, // VDD_Clock + {PciClk3, Enabled, All}, // 33M_S1 + {PciClk4, Enabled, All}, // 33M_PA +}; + +// +// Dynamic clock table +// This is used to determine if a clock should be left on or turned off based +// on the presence of a device. The bridge information is used so the bus +// number for the device to be detected can be found. +// + +// +// ClockSxInfo Table +// This is a list of clocks that need to be set to a known state when the +// system enters S4 or S5. +// +EFI_STATIC_SIGNALS mRvpSxClocks[] = { + {SaveClockConfiguration, Disabled, All} +}; + +// +// RVP settings structure +// +EFI_CLOCK_PLATFORM_INFO mRvpClockSettings = { + mRvpStaticClocks, + sizeof(mRvpStaticClocks) / sizeof(mRvpStaticClocks[0]), + 0, // No clocks will be turned off mRvpDynamicClocks, + 0, // No clocks will be turned off sizeof(mRvpDynamicClocks) / sizeof(mRvpDynamicClocks[0]), + mRvpSxClocks, + sizeof(mRvpSxClocks) / sizeof(mRvpSxClocks[0]) +}; +#endif + +VOID +InitializeClockRouting( + ) +{ + EFI_STATUS Status; + UINTN BoardIdVarSize; + EFI_BOARD_FEATURES BoardIdVar; + EFI_CLOCK_PLATFORM_INFO *ClockPolicy; + EFI_HANDLE Handle; + + ClockPolicy = &mDefClockPolicy; + + // + // Do modifications based on board type + // + BoardIdVarSize = sizeof (EFI_BOARD_FEATURES); + Status = gRT->GetVariable ( + BOARD_FEATURES_NAME, + &gEfiBoardFeaturesGuid, + NULL, + &BoardIdVarSize, + &BoardIdVar + ); + if (!EFI_ERROR (Status)) { + +#if defined( RVP_SUPPORT ) && RVP_SUPPORT + if (BoardIdVar & B_BOARD_FEATURES_RVP) { + ClockPolicy = &mRvpClockSettings; + } +#else + + // + // Isolate board type information + // + BoardIdVar = BoardIdVar & (B_BOARD_FEATURES_FORM_FACTOR_ATX | + B_BOARD_FEATURES_FORM_FACTOR_BTX | + B_BOARD_FEATURES_FORM_FACTOR_MICRO_ATX | + B_BOARD_FEATURES_FORM_FACTOR_MICRO_BTX); + + if (BoardIdVar == B_BOARD_FEATURES_FORM_FACTOR_ATX || + BoardIdVar == B_BOARD_FEATURES_FORM_FACTOR_MICRO_ATX) { + ClockPolicy = &mAtxClockSettings; + } + +#endif + + } + + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiCk505ClockPlatformInfoGuid, + EFI_NATIVE_INTERFACE, + ClockPolicy + ); + ASSERT_EFI_ERROR(Status); + +} + + diff --git a/Vlv2TbltDevicePkg/PlatformDxe/Configuration.h b/Vlv2TbltDevicePkg/PlatformDxe/Configuration.h new file mode 100644 index 0000000000..08bdf07e60 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/Configuration.h @@ -0,0 +1,697 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + Configuration.h + +Abstract: + + Driver configuration include file + + +--*/ + +#ifndef _CONFIGURATION_H +#define _CONFIGURATION_H + +#define EFI_NON_DEVICE_CLASS 0x00 +#define EFI_DISK_DEVICE_CLASS 0x01 +#define EFI_VIDEO_DEVICE_CLASS 0x02 +#define EFI_NETWORK_DEVICE_CLASS 0x04 +#define EFI_INPUT_DEVICE_CLASS 0x08 +#define EFI_ON_BOARD_DEVICE_CLASS 0x10 +#define EFI_OTHER_DEVICE_CLASS 0x20 + +// +// Processor labels +// +#define PROCESSOR_HT_MODE 0x0100 +#define PROCESSOR_FSB_MULTIPLIER 0x0101 +#define PROCESSOR_MULTIPLIER_OVERRIDE_CONTROL 0x0211 + +// +// Memory labels +// +#define MEMORY_SLOT1_SPEED 0x0200 +#define MEMORY_SLOT2_SPEED 0x0201 +#define MEMORY_SLOT3_SPEED 0x0202 +#define MEMORY_SLOT4_SPEED 0x0203 +#define END_MEMORY_SLOT_SPEED 0x020F +#define PERFORMANCE_MEMORY_PROFILE_CONTROL 0x0210 +#define UCLK_RATIO_CONTROL 0x0212 + +// +// Language label +// +#define FRONT_PAGE_ITEM_LANGUAGE 0x300 + +// +// Boot Labels +// +#define BOOT_DEVICE_PRIORITY_BEGIN 0x0400 +#define BOOT_DEVICE_PRIORITY_END 0x0401 +#define BOOT_OPTICAL_DEVICE_BEGIN 0x0410 +#define BOOT_OPTICAL_DEVICE_END 0x0411 +#define BOOT_REMOVABLE_DEVICE_BEGIN 0x0420 +#define BOOT_REMOVABLE_DEVICE_END 0x0421 +#define BOOT_PXE_DEVICE_BEGIN 0x0430 +#define BOOT_PXE_DEVICE_END 0x0431 +#define BOOT_MENU_TYPE_BEGIN 0x0440 +#define BOOT_MENU_TYPE_END 0x0441 +#define BOOT_USB_DEVICE_BEGIN 0x0450 +#define BOOT_USB_DEVICE_END 0x0451 +#define BOOT_USB_FIRST_BEGIN 0x0460 +#define BOOT_USB_FIRST_END 0x0461 +#define BOOT_UEFI_BEGIN 0x0470 +#define BOOT_UEFI_END 0x0471 +#define BOOT_USB_UNAVAILABLE_BEGIN 0x0480 +#define BOOT_USB_UNAVAILABLE_END 0x0481 +#define BOOT_CD_UNAVAILABLE_BEGIN 0x0490 +#define BOOT_CD_UNAVAILABLE_END 0x0491 +#define BOOT_FDD_UNAVAILABLE_BEGIN 0x04A0 +#define BOOT_FDD_UNAVAILABLE_END 0x04A1 +#define BOOT_DEVICE_PRIORITY_DEFAULT_BEGIN 0x04B0 +#define BOOT_DEVICE_PRIORITY_DEFAULT_END 0x04B1 +#define BOOT_USB_OPT_LABEL_BEGIN 0x04C0 +#define BOOT_USB_OPT_LABEL_END 0x04C1 + +#define VAR_EQ_ADMIN_NAME 0x0041 // A +#define VAR_EQ_ADMIN_DECIMAL_NAME L"65" +#define VAR_EQ_VIEW_ONLY_NAME 0x0042 // B +#define VAR_EQ_VIEW_ONLY_DECIMAL_NAME L"66" +#define VAR_EQ_CONFIG_MODE_NAME 0x0043 // C +#define VAR_EQ_CONFIG_MODE_DECIMAL_NAME L"67" +#define VAR_EQ_CPU_EE_NAME 0x0045 // E +#define VAR_EQ_CPU_EE_DECIMAL_NAME L"69" +#define VAR_EQ_FLOPPY_MODE_NAME 0x0046 // F +#define VAR_EQ_FLOPPY_MODE_DECIMAL_NAME L"70" +#define VAR_EQ_HT_MODE_NAME 0x0048 // H +#define VAR_EQ_HT_MODE_DECIMAL_NAME L"72" +#define VAR_EQ_AHCI_MODE_NAME 0x0049 // I +#define VAR_EQ_AHCI_MODE_DECIMAL_NAME L"73" +#define VAR_EQ_CPU_LOCK_NAME 0x004C // L +#define VAR_EQ_CPU_LOCK_DECIMAL_NAME L"76" +#define VAR_EQ_NX_MODE_NAME 0x004E // N +#define VAR_EQ_NX_MODE_DECIMAL_NAME L"78" +#define VAR_EQ_RAID_MODE_NAME 0x0052 // R +#define VAR_EQ_RAID_MODE_DECIMAL_NAME L"82" +#define VAR_EQ_1394_MODE_NAME 0x0054 // T +#define VAR_EQ_1394_MODE_DECIMAL_NAME L"84" +#define VAR_EQ_USER_NAME 0x0055 // U +#define VAR_EQ_USER_DECIMAL_NAME L"85" +#define VAR_EQ_VIDEO_MODE_NAME 0x0056 // V +#define VAR_EQ_VIDEO_MODE_DECIMAL_NAME L"86" +#define VAR_EQ_LEGACY_FP_AUDIO_NAME 0x0057 // W +#define VAR_EQ_LEGACY_FP_AUDIO_DECIMAL_NAME L"87" +#define VAR_EQ_EM64T_CAPABLE_NAME 0x0058 // X +#define VAR_EQ_EM64T_CAPABLE_DECIMAL_NAME L"88" +#define VAR_EQ_BOARD_FORMFACTOR_NAME 0x0059 // Y +#define VAR_EQ_BOARD_FORMFACTOR_DECIMAL_NAME L"89" +#define VAR_EQ_UNCON_CPU_NAME 0x005B // ?? +#define VAR_EQ_UNCON_CPU_DECIMAL_NAME L"91" +#define VAR_EQ_VAR_HIDE_NAME 0x005C // ?? +#define VAR_EQ_VAR_HIDE_DECIMAL_NAME L"92" +#define VAR_EQ_ENERGY_LAKE_NAME 0x005D // ?? +#define VAR_EQ_ENERGY_LAKE_DECIMAL_NAME L"93" +#define VAR_EQ_TPM_MODE_NAME 0x005E // ^ +#define VAR_EQ_TPM_MODE_DECIMAL_NAME L"94" +#define VAR_EQ_DISCRETE_SATA_NAME 0x005F // ?? +#define VAR_EQ_DISCRETE_SATA_DECIMAL_NAME L"95" +#define VAR_EQ_ROEM_SKU_NAME 0x0060 // ?? +#define VAR_EQ_ROEM_SKU_DECIMAL_NAME L"96" +#define VAR_EQ_AMTSOL_MODE_NAME 0x0061 // ?? +#define VAR_EQ_AMTSOL_MODE_DECIMAL_NAME L"97" +#define VAR_EQ_NO_PEG_MODE_NAME 0x0062 // ?? +#define VAR_EQ_NO_PEG_MODE_DECIMAL_NAME L"98" +#define VAR_EQ_SINGLE_PROCESSOR_MODE_NAME 0x0063 // ?? +#define VAR_EQ_SINGLE_PROCESSOR_MODE_DECIMAL_NAME L"99" +#define VAR_EQ_FLOPPY_HIDE_NAME 0x0064 // ?? +#define VAR_EQ_FLOPPY_HIDE_DECIMAL_NAME L"100" +#define VAR_EQ_SERIAL_HIDE_NAME 0x0065 // ?? +#define VAR_EQ_SERIAL_HIDE_DECIMAL_NAME L"101" +#define VAR_EQ_GV3_CAPABLE_NAME 0x0066 // f +#define VAR_EQ_GV3_CAPABLE_DECIMAL_NAME L"102" +#define VAR_EQ_2_MEMORY_NAME 0x0067 // ?? +#define VAR_EQ_2_MEMORY_DECIMAL_NAME L"103" +#define VAR_EQ_2_SATA_NAME 0x0068 // ?? +#define VAR_EQ_2_SATA_DECIMAL_NAME L"104" +#define VAR_EQ_NEC_SKU_NAME 0x0069 // ?? +#define VAR_EQ_NEC_SKU_DECIMAL_NAME L"105" +#define VAR_EQ_AMT_MODE_NAME 0x006A // ?? +#define VAR_EQ_AMT_MODE_DECIMAL_NAME L"106" +#define VAR_EQ_LCLX_SKU_NAME 0x006B // ?? +#define VAR_EQ_LCLX_SKU_DECIMAL_NAME L"107" +#define VAR_EQ_VT_NAME 0x006C +#define VAR_EQ_VT_DECIMAL_NAME L"108" +#define VAR_EQ_LT_NAME 0x006D +#define VAR_EQ_LT_DECIMAL_NAME L"109" +#define VAR_EQ_ITK_BIOS_MOD_NAME 0x006E // ?? +#define VAR_EQ_ITK_BIOS_MOD_DECIMAL_NAME L"110" +#define VAR_EQ_HPET_NAME 0x006F +#define VAR_EQ_HPET_DECIMAL_NAME L"111" +#define VAR_EQ_ADMIN_INSTALLED_NAME 0x0070 // ?? +#define VAR_EQ_ADMIN_INSTALLED_DECIMAL_NAME L"112" +#define VAR_EQ_USER_INSTALLED_NAME 0x0071 // ?? +#define VAR_EQ_USER_INSTALLED_DECIMAL_NAME L"113" +#define VAR_EQ_CPU_CMP_NAME 0x0072 +#define VAR_EQ_CPU_CMP_DECIMAL_NAME L"114" +#define VAR_EQ_LAN_MAC_ADDR_NAME 0x0073 // ?? +#define VAR_EQ_LAN_MAC_ADDR_DECIMAL_NAME L"115" +#define VAR_EQ_PARALLEL_HIDE_NAME 0x0074 // ?? +#define VAR_EQ_PARALLEL_HIDE_DECIMAL_NAME L"116" +#define VAR_EQ_AFSC_SETUP_NAME 0x0075 +#define VAR_EQ_AFSC_SETUP_DECIMAL_NAME L"117" +#define VAR_EQ_MINICARD_MODE_NAME 0x0076 // +#define VAR_EQ_MINICARD_MODE_DECIMAL_NAME L"118" +#define VAR_EQ_VIDEO_IGD_NAME 0x0077 // +#define VAR_EQ_VIDEO_IGD_DECIMAL_NAME L"119" +#define VAR_EQ_ALWAYS_ENABLE_LAN_NAME 0x0078 // +#define VAR_EQ_ALWAYS_ENABLE_LAN_DECIMAL_NAME L"120" +#define VAR_EQ_LEGACY_FREE_NAME 0x0079 // +#define VAR_EQ_LEGACY_FREE_DECIMAL_NAME L"121" +#define VAR_EQ_CLEAR_CHASSIS_INSTRUSION_STATUS_NAME 0x007A +#define VAR_EQ_CLEAR_CHASSIS_INSTRUSION_STATUS_DECIMAL_NAME L"122" +#define VAR_EQ_CPU_FSB_NAME 0x007B // +#define VAR_EQ_CPU_FSB_DECIMAL_NAME L"123" +#define VAR_EQ_SATA0_DEVICE_NAME 0x007C // +#define VAR_EQ_SATA0_DVICE_DECIMAL_NAME L"124" +#define VAR_EQ_SATA1_DEVICE_NAME 0x007D // +#define VAR_EQ_SATA1_DVICE_DECIMAL_NAME L"125" +#define VAR_EQ_SATA2_DEVICE_NAME 0x007E // +#define VAR_EQ_SATA2_DVICE_DECIMAL_NAME L"126" +#define VAR_EQ_SATA3_DEVICE_NAME 0x007F // +#define VAR_EQ_SATA3_DVICE_DECIMAL_NAME L"127" +#define VAR_EQ_SATA4_DEVICE_NAME 0x0080 // +#define VAR_EQ_SATA4_DVICE_DECIMAL_NAME L"128" +#define VAR_EQ_SATA5_DEVICE_NAME 0x0081 // +#define VAR_EQ_SATA5_DVICE_DECIMAL_NAME L"129" +#define VAR_EQ_TPM_STATUS_NAME 0x0082 // To indicate if TPM is enabled +#define VAR_EQ_TPM_STATUS_DECIMAL_NAME L"130" +#define VAR_EQ_HECETA6E_PECI_CPU_NAME 0x0083 +#define VAR_EQ_HECETA6E_PECI_CPU_DECIMAL_NAME L"131" +#define VAR_EQ_USB_2_NAME 0x0084 // +#define VAR_EQ_USB_2_DECIMAL_NAME L"132" +#define VAR_EQ_RVP_NAME 0x0085 // +#define VAR_EQ_RVP_DECIMAL_NAME L"133" +#define VAR_EQ_ECIR_NAME 0x0086 +#define VAR_EQ_ECIR_DECIMAL_NAME L"134" +#define VAR_EQ_WAKONS5KB_NAME 0x0087 +#define VAR_EQ_WAKONS5KB_DECIMAL_NAME L"135" +#define VAR_EQ_HDAUDIOLINKBP_NAME 0x0088 +#define VAR_EQ_HDAUDIOLINKBP_DECIMAL_NAME L"136" +#define VAR_EQ_FINGERPRINT_NAME 0x0089 +#define VAR_EQ_FINGERPRINT_DECIMAL_NAME L"137" +#define VAR_EQ_BLUETOOTH_NAME 0x008A +#define VAR_EQ_BLUETOOTH_DECIMAL_NAME L"138" +#define VAR_EQ_WLAN_NAME 0x008B +#define VAR_EQ_WLAN_DECIMAL_NAME L"139" +#define VAR_EQ_1_PATA_NAME 0x008C +#define VAR_EQ_1_PATA_DECIMAL_NAME L"140" +#define VAR_EQ_ACTIVE_PROCESSOR_CORE_NAME 0x008D +#define VAR_EQ_ACTIVE_PROCESSOR_CORE_DECIMAL_NAME L"141" +#define VAR_EQ_TURBO_MODE_CAP_NAME 0x008E +#define VAR_EQ_TURBO_MODE_CAP_DECIMAL_NAME L"142" +#define VAR_EQ_XE_MODE_CAP_NAME 0x008F +#define VAR_EQ_XE_MODE_CAP_DECIMAL_NAME L"143" +#define VAR_EQ_NPI_QPI_VOLTAGE_NAME 0x0090 +#define VAR_EQ_NPI_QPI_VOLTAGE_DECIMAL_NAME L"144" +#define VAR_EQ_PRE_PROD_NON_XE_NAME 0x0091 +#define VAR_EQ_PRE_PROD_NON_XE_DECIMAL_NAME L"145" +#define VAR_EQ_2_C0_MEMORY_NAME 0x0092 // ?? +#define VAR_EQ_2_C0_MEMORY_DECIMAL_NAME L"146" +#define VAR_EQ_LVDS_NAME 0x0093 +#define VAR_EQ_LVDS_DECIMAL_NAME L"147" +#define VAR_EQ_USB_OPTION_SHOW_NAME 0x0094 +#define VAR_EQ_USB_OPTION_SHOW_DECIMAL_NAME L"148" +#define VAR_EQ_HDD_MASTER_INSTALLED_NAME 0x0095 +#define VAR_EQ_HDD_MASTER_INSTALLED_DECIMAL_NAME L"149" +#define VAR_EQ_HDD_USER_INSTALLED_NAME 0x0096 +#define VAR_EQ_HDD_USER_INSTALLED_DECIMAL_NAME L"150" +#define VAR_EQ_PS2_HIDE_NAME 0x0097 // ?? +#define VAR_EQ_PS2_HIDE_DECIMAL_NAME L"151" +#define VAR_EQ_VIDEO_SLOT_NAME 0x0098 +#define VAR_EQ_VIDEO_SLOT_DECIMAL_NAME L"152" +#define VAR_EQ_HDMI_SLOT_NAME 0x0099 +#define VAR_EQ_HDMI_SLOT_DECIMAL_NAME L"153" +#define VAR_EQ_SERIAL2_HIDE_NAME 0x009a +#define VAR_EQ_SERIAL2_HIDE_DECIMAL_NAME L"154" + + +#define VAR_EQ_LVDS_WARNING_HIDE_NAME 0x009e +#define VAR_EQ_LVDS_WARNING_HIDE_DECIMAL_NAME L"158" + + +#define VAR_EQ_MSATA_HIDE_NAME 0x009f +#define VAR_EQ_MSATA_HIDE_DECIMAL_NAME L"159" + + +#define VAR_EQ_PCI_SLOT1_NAME 0x00a0 +#define VAR_EQ_PCI_SLOT1_DECIMAL_NAME L"160" +#define VAR_EQ_PCI_SLOT2_NAME 0x00a1 +#define VAR_EQ_PCI_SLOT2_DECIMAL_NAME L"161" + +// +// Generic Form Ids +// +#define ROOT_FORM_ID 1 + +// +// Advance Page. Do not have to be sequential but have to be unique +// +#define CONFIGURATION_ROOT_FORM_ID 2 +#define BOOT_CONFIGURATION_ID 3 +#define ONBOARDDEVICE_CONFIGURATION_ID 4 +#define DRIVE_CONFIGURATION_ID 5 +#define FLOPPY_CONFIGURATION_ID 6 +#define EVENT_LOG_CONFIGURATION_ID 7 +#define VIDEO_CONFIGURATION_ID 8 +#define USB_CONFIGURATION_ID 9 +#define HARDWARE_MONITOR_CONFIGURATION_ID 10 +#define VIEW_EVENT_LOG_CONFIGURATION_ID 11 +#define MEMORY_OVERRIDE_ID 12 +#define CHIPSET_CONFIGURATION_ID 13 +#define BURN_IN_MODE_ID 14 +#define PCI_EXPRESS_ID 15 +#define MANAGEMENT_CONFIGURATION_ID 16 +#define CPU_CONFIGURATION_ID 17 +#define PCI_CONFIGURATION_ID 18 +#define SECURITY_CONFIGURATION_ID 19 +#define ZIP_CONFIGURATION_ID 20 +#define AFSC_FAN_CONTROL_ID 21 +#define VFR_FORMID_CSI 22 +#define VFR_FORMID_MEMORY 23 +#define VFR_FORMID_IOH 24 +#define VFR_FORMID_CPU_CSI 25 +#define VFR_FORMID_IOH_CONFIG 26 +#define VFR_FORMID_VTD 27 +#define VFR_FORMID_PCIE_P0 28 +#define VFR_FORMID_PCIE_P1 29 +#define VFR_FORMID_PCIE_P2 30 +#define VFR_FORMID_PCIE_P3 31 +#define VFR_FORMID_PCIE_P4 32 +#define VFR_FORMID_PCIE_P5 33 +#define VFR_FORMID_PCIE_P6 34 +#define VFR_FORMID_PCIE_P7 35 +#define VFR_FORMID_PCIE_P8 36 +#define VFR_FORMID_PCIE_P9 37 +#define VFR_FORMID_PCIE_P10 38 +#define VFR_FID_SKT0 39 +#define VFR_FID_IOH0 40 +#define VFR_FID_IOH_DEV_HIDE 41 +#define PROCESSOR_OVERRIDES_FORM_ID 42 +#define BUS_OVERRIDES_FORM_ID 43 +#define REF_OVERRIDES_FORM_ID 44 +#define MEMORY_INFORMATION_ID 45 +#define LVDS_WARNING_ID 46 +#define LVDS_CONFIGURATION_ID 47 +#define PCI_SLOT_CONFIGURATION_ID 48 +#define HECETA_CONFIGURATION_ID 49 +#define LVDS_EXPERT_CONFIGURATION_ID 50 +#define PCI_SLOT_7_ID 51 +#define PCI_SLOT_6_ID 52 +#define PCI_SLOT_5_ID 53 +#define PCI_SLOT_4_ID 54 +#define PCI_SLOT_3_ID 55 +#define PCI_SLOT_2_ID 56 +#define PCI_SLOT_1_ID 57 +#define BOOT_DISPLAY_ID 58 +#define CPU_PWR_CONFIGURATION_ID 59 + +#define FSC_CONFIGURATION_ID 60 +#define FSC_CPU_TEMPERATURE_FORM_ID 61 +#define FSC_VTT_VOLTAGE_FORM_ID 62 +#define FSC_FEATURES_CONTROL_ID 63 +#define FSC_FAN_CONFIGURATION_ID 64 +#define FSC_PROCESSOR_FAN_CONFIGURATION_ID 65 +#define FSC_FRONT_FAN_CONFIGURATION_ID 66 +#define FSC_REAR_FAN_CONFIGURATION_ID 67 +#define FSC_AUX_FAN_CONFIGURATION_ID 68 +#define FSC_12_VOLTAGE_FORM_ID 69 +#define FSC_5_VOLTAGE_FORM_ID 70 +#define FSC_3P3_VOLTAGE_FORM_ID 71 +#define FSC_2P5_VOLTAGE_FORM_ID 72 +#define FSC_VCC_VOLTAGE_FORM_ID 73 +#define FSC_PCH_TEMPERATURE_FORM_ID 74 +#define FSC_MEM_TEMPERATURE_FORM_ID 75 +#define FSC_VR_TEMPERATURE_FORM_ID 76 +#define FSC_3P3STANDBY_VOLTAGE_FORM_ID 77 +#define FSC_5BACKUP_VOLTAGE_FORM_ID 78 +#define ROOT_MAIN_FORM_ID 79 +#define ROOT_BOOT_FORM_ID 80 +#define ROOT_MAINTENANCE_ID 81 +#define ROOT_POWER_FORM_ID 82 +#define ROOT_SECURITY_FORM_ID 83 +#define ROOT_PERFORMANCE_FORM_ID 84 +#define ROOT_SYSTEM_SETUP_FORM_ID 85 + +#define ADDITIONAL_SYSTEM_INFO_FORM_ID 86 + +#define THERMAL_CONFIG_FORM_ID 87 + +#define PCI_SLOT_CONFIG_LABEL_ID_1 0x300A +#define PCI_SLOT_CONFIG_LABEL_ID_2 0x300B +#define PCI_SLOT_CONFIG_LABEL_ID_3 0x300C +#define PCI_SLOT_CONFIG_LABEL_ID_4 0x300D +#define PCI_SLOT_CONFIG_LABEL_ID_5 0x300E +#define PCI_SLOT_CONFIG_LABEL_ID_6 0x300F +#define PCI_SLOT_CONFIG_LABEL_ID_7 0x3010 +#define PCI_SLOT_CONFIG_LABEL_ID_8 0x3011 + +// +// Advance Hardware Monitor Callback Keys. Do not have to be sequential but have to be unique +// +#define CONFIGURATION_HARDWARE_CALLBACK_KEY 0x2000 +#define ADVANCE_VIDEO_CALLBACK_KEY 0x2001 +#define CONFIGURATION_FSC_CALLBACK_KEY 0x2002 +#define CONFIGURATION_RESTORE_FAN_CONTROL_CALLBACK_KEY 0x2003 +#define CONFIGURATION_LVDS_CALLBACK_KEY 0x2004 +#define CONFIGURATION_PREDEFINED_EDID_CALLBACK_KEY 0x2005 +#define ADVANCE_LVDS_CALLBACK_KEY 0x2010 + +// +// Main Callback Keys. Do not have to be sequential but have to be unique +// +#define MAIN_LANGUAGE_CALLBACK_KEY 0x3000 + +// +// Power Hardware Monitor Callback Keys. Do not have to be sequential but have to be unique +// +#define POWER_HARDWARE_CALLBACK_KEY 0x4000 + +// +// Performance Callback Keys. Do not have to be sequential but have to be unique +// +#define PROCESSOR_OVERRIDES_CALLBACK_KEY 0x5000 +#define PERFORMANCE_CALLBACK_KEY 0x5001 +#define BUS_OVERRIDES_CALLBACK_KEY 0x5002 +#define MEMORY_CFG_CALLBACK_KEY 0x5003 +#define PERFORMANCE_STATUS_CALLBACK_KEY 0x5004 +#define MEMORY_RATIO_CALLBACK_KEY 0x5005 +#define MEMORY_MODE_CALLBACK_KEY 0x5006 + +// +// Security Callback Keys. Do not have to be sequential but have to be unique +// +#define SECURITY_SUPERVISOR_CALLBACK_KEY 0x1000 +#define SECURITY_USER_CALLBACK_KEY 0x1001 +#define SECURITY_CLEAR_ALL_CALLBACK_KEY 0x1002 +#define SECURITY_CLEAR_USER_CALLBACK_KEY 0x1004 +#define SECURITY_RESET_AMT_CALLBACK_KEY 0x1008 +#define SECURITY_CHANGE_VT_CALLBACK_KEY 0x1010 +#define SECURITY_MASTER_HDD_CALLBACK_KEY 0x1020 +#define SECURITY_USER_HDD_CALLBACK_KEY 0x1040 + +// +// Boot Callback Keys. Do not have to be sequential but have to be unique +// +#define BOOT_HYPERBOOT_CALLBACK_KEY 0x6003 +#define BOOT_HYPERBOOT_CALLBACK_KEY_DISABLE 0x6004 +#define BOOT_HYPERBOOT_CALLBACK_KEY_USB 0x6005 +#define BOOT_HYPERBOOT_CALLBACK_KEY_DISABLE_USB_OPT 0x6006 + +// +// IDCC/Setup FSB Frequency Override Range +// +#define EFI_IDCC_FSB_MIN 133 +#define EFI_IDCC_FSB_MAX 240 +#define EFI_IDCC_FSB_STEP 1 + +// +// Reference voltage +// +#define EFI_REF_DAC_MIN 0 +#define EFI_REF_DAC_MAX 255 +#define EFI_GTLREF_DEF 170 +#define EFI_DDRREF_DEF 128 +#define EFI_DIMMREF_DEF 128 + +// +// Setup FSB Frequency Override Range +// +#define EFI_FSB_MIN 133 +#define EFI_FSB_MAX 240 +#define EFI_FSB_STEP 1 +#define EFI_FSB_AUTOMATIC 0 +#define EFI_FSB_MANUAL 1 +#define FSB_FREQ_ENTRY_COUNT ((EFI_FSB_MAX - EFI_FSB_MIN)/EFI_FSB_STEP) + 1 +#define FSB_FREQ_ENTRY_TYPE UINT16_TYPE + +// +// Setup processor multiplier range +// +#define EFI_PROC_MULT_MIN 5 +#define EFI_PROC_MULT_MAX 40 +#define EFI_PROC_MULT_STEP 1 +#define EFI_PROC_AUTOMATIC 0 +#define EFI_PROC_MANUAL 1 +#define PROC_MULT_ENTRY_COUNT ((EFI_PROC_MULT_MAX - EFI_PROC_MULT_MIN)/EFI_PROC_MULT_STEP) + 1 +#define PROC_MULT_ENTRY_TYPE UINT8_TYPE + +// +// PCI Express Definitions +// +#define EFI_PCIE_FREQ_DEF 0x0 + +#define PCIE_FREQ_ENTRY_TYPE UINT8_TYPE +#define PCIE_FREQ_ENTRY_7 0x7 +#define PCIE_FREQ_ENTRY_6 0x6 +#define PCIE_FREQ_ENTRY_5 0x5 +#define PCIE_FREQ_ENTRY_4 0x4 +#define PCIE_FREQ_ENTRY_3 0x3 +#define PCIE_FREQ_ENTRY_2 0x2 +#define PCIE_FREQ_ENTRY_1 0x1 +#define PCIE_FREQ_ENTRY_0 0x0 + +#define PCIE_FREQ_TRANSLATION_TABLE_ENTRIES 8 +#define PCIE_FREQ_TRANSLATION_TABLE { PCIE_FREQ_ENTRY_0, \ + PCIE_FREQ_ENTRY_1, \ + PCIE_FREQ_ENTRY_2, \ + PCIE_FREQ_ENTRY_3, \ + PCIE_FREQ_ENTRY_4, \ + PCIE_FREQ_ENTRY_5, \ + PCIE_FREQ_ENTRY_6, \ + PCIE_FREQ_ENTRY_7 } + + +#define PCIE_FREQ_PRECISION 2 +#define PCIE_FREQ_VALUE_7 10924 +#define PCIE_FREQ_VALUE_6 10792 +#define PCIE_FREQ_VALUE_5 10660 +#define PCIE_FREQ_VALUE_4 10528 +#define PCIE_FREQ_VALUE_3 10396 +#define PCIE_FREQ_VALUE_2 10264 +#define PCIE_FREQ_VALUE_1 10132 +#define PCIE_FREQ_VALUE_0 10000 + +#define PCIE_FREQ_VALUES { PCIE_FREQ_VALUE_0, \ + PCIE_FREQ_VALUE_1, \ + PCIE_FREQ_VALUE_2, \ + PCIE_FREQ_VALUE_3, \ + PCIE_FREQ_VALUE_4, \ + PCIE_FREQ_VALUE_5, \ + PCIE_FREQ_VALUE_6, \ + PCIE_FREQ_VALUE_7 } + +// +// Memory Frequency Definitions +// +#define MEMORY_REF_FREQ_ENTRY_DEF 0x08 + +#define MEMORY_REF_FREQ_ENTRY_TYPE UINT8_TYPE +#define MEMORY_REF_FREQ_ENTRY_3 0x04 +#define MEMORY_REF_FREQ_ENTRY_2 0x00 +#define MEMORY_REF_FREQ_ENTRY_1 0x02 +#define MEMORY_REF_FREQ_ENTRY_0 0x01 + +#define MEMORY_REF_FREQ_TRANSLATION_TABLE_ENTRIES 4 +#define MEMORY_REF_FREQ_TRANSLATION_TABLE { MEMORY_REF_FREQ_ENTRY_0, \ + MEMORY_REF_FREQ_ENTRY_1, \ + MEMORY_REF_FREQ_ENTRY_2, \ + MEMORY_REF_FREQ_ENTRY_3 } + +#define MEMORY_REF_FREQ_PRECISION 0 +#define MEMORY_REF_FREQ_VALUE_3 333 +#define MEMORY_REF_FREQ_VALUE_2 267 +#define MEMORY_REF_FREQ_VALUE_1 200 +#define MEMORY_REF_FREQ_VALUE_0 133 + +#define MEMORY_REF_FREQ_VALUES { MEMORY_REF_FREQ_VALUE_0, \ + MEMORY_REF_FREQ_VALUE_1, \ + MEMORY_REF_FREQ_VALUE_2, \ + MEMORY_REF_FREQ_VALUE_3 } + + +// +// Memory Reference Frequency Definitions +// + +#define MEMORY_FREQ_ENTRY_TYPE UINT8_TYPE +#define MEMORY_FREQ_ENTRY_3 0x4 +#define MEMORY_FREQ_ENTRY_2 0x3 +#define MEMORY_FREQ_ENTRY_1 0x2 +#define MEMORY_FREQ_ENTRY_0 0x1 + +#define MEMORY_FREQ_TRANSLATION_TABLE_ENTRIES 4 +#define MEMORY_FREQ_TRANSLATION_TABLE { MEMORY_FREQ_ENTRY_0, \ + MEMORY_FREQ_ENTRY_1, \ + MEMORY_FREQ_ENTRY_2, \ + MEMORY_FREQ_ENTRY_3 } + + +#define MEMORY_FREQ_MULT_PRECISION 2 +#define MEMORY_FREQ_MULT_333MHZ_VALUE_3 240 +#define MEMORY_FREQ_MULT_333MHZ_VALUE_2 200 +#define MEMORY_FREQ_MULT_333MHZ_VALUE_1 160 +#define MEMORY_FREQ_MULT_333MHZ_VALUE_0 120 + +#define MEMORY_FREQ_MULT_266MHZ_VALUE_3 300 +#define MEMORY_FREQ_MULT_266MHZ_VALUE_2 250 +#define MEMORY_FREQ_MULT_266MHZ_VALUE_1 200 +#define MEMORY_FREQ_MULT_266MHZ_VALUE_0 150 + +#define MEMORY_FREQ_MULT_200MHZ_VALUE_3 400 +#define MEMORY_FREQ_MULT_200MHZ_VALUE_2 333 +#define MEMORY_FREQ_MULT_200MHZ_VALUE_1 267 +#define MEMORY_FREQ_MULT_200MHZ_VALUE_0 200 + +#define MEMORY_FREQ_MULT_133MHZ_VALUE_3 600 +#define MEMORY_FREQ_MULT_133MHZ_VALUE_2 500 +#define MEMORY_FREQ_MULT_133MHZ_VALUE_1 400 +#define MEMORY_FREQ_MULT_133MHZ_VALUE_0 300 + +#define MEMORY_FREQ_MULT_333MHZ_VALUES { MEMORY_FREQ_MULT_333MHZ_VALUE_0, \ + MEMORY_FREQ_MULT_333MHZ_VALUE_1, \ + MEMORY_FREQ_MULT_333MHZ_VALUE_2, \ + MEMORY_FREQ_MULT_333MHZ_VALUE_3 } + +#define MEMORY_FREQ_MULT_266MHZ_VALUES { MEMORY_FREQ_MULT_266MHZ_VALUE_0, \ + MEMORY_FREQ_MULT_266MHZ_VALUE_1, \ + MEMORY_FREQ_MULT_266MHZ_VALUE_2, \ + MEMORY_FREQ_MULT_266MHZ_VALUE_3 } + +#define MEMORY_FREQ_MULT_200MHZ_VALUES { MEMORY_FREQ_MULT_200MHZ_VALUE_0, \ + MEMORY_FREQ_MULT_200MHZ_VALUE_1, \ + MEMORY_FREQ_MULT_200MHZ_VALUE_2, \ + MEMORY_FREQ_MULT_200MHZ_VALUE_3 } + +#define MEMORY_FREQ_MULT_133MHZ_VALUES { MEMORY_FREQ_MULT_133MHZ_VALUE_0, \ + MEMORY_FREQ_MULT_133MHZ_VALUE_1, \ + MEMORY_FREQ_MULT_133MHZ_VALUE_2, \ + MEMORY_FREQ_MULT_133MHZ_VALUE_3 } + +// +// CAS Memory Timing Definitions +// + +#define MEMORY_TCL_ENTRY_TYPE UINT8_TYPE +#define MEMORY_TCL_ENTRY_3 0x2 +#define MEMORY_TCL_ENTRY_2 0x1 +#define MEMORY_TCL_ENTRY_1 0x0 +#define MEMORY_TCL_ENTRY_0 0x3 + +#define MEMORY_TCL_TRANSLATION_TABLE_ENTRIES 4 +#define MEMORY_TCL_TRANSLATION_TABLE { MEMORY_TCL_ENTRY_0, \ + MEMORY_TCL_ENTRY_1, \ + MEMORY_TCL_ENTRY_2, \ + MEMORY_TCL_ENTRY_3 } + + +#define MEMORY_TCL_PRECISION 0 +#define MEMORY_TCL_VALUE_3 3 +#define MEMORY_TCL_VALUE_2 4 +#define MEMORY_TCL_VALUE_1 5 +#define MEMORY_TCL_VALUE_0 6 + +#define MEMORY_TCL_VALUES { MEMORY_TCL_VALUE_0, \ + MEMORY_TCL_VALUE_1, \ + MEMORY_TCL_VALUE_2, \ + MEMORY_TCL_VALUE_3 } + + +// +// TRCD Memory Timing Definitions +// + +#define MEMORY_TRCD_ENTRY_TYPE UINT8_TYPE +#define MEMORY_TRCD_ENTRY_3 0x0 +#define MEMORY_TRCD_ENTRY_2 0x1 +#define MEMORY_TRCD_ENTRY_1 0x2 +#define MEMORY_TRCD_ENTRY_0 0x3 + +#define MEMORY_TRCD_TRANSLATION_TABLE_ENTRIES 4 +#define MEMORY_TRCD_TRANSLATION_TABLE { MEMORY_TRCD_ENTRY_0, \ + MEMORY_TRCD_ENTRY_1, \ + MEMORY_TRCD_ENTRY_2, \ + MEMORY_TRCD_ENTRY_3 } + + +#define MEMORY_TRCD_PRECISION 0 +#define MEMORY_TRCD_VALUE_3 2 +#define MEMORY_TRCD_VALUE_2 3 +#define MEMORY_TRCD_VALUE_1 4 +#define MEMORY_TRCD_VALUE_0 5 + +#define MEMORY_TRCD_VALUES { MEMORY_TRCD_VALUE_0, \ + MEMORY_TRCD_VALUE_1, \ + MEMORY_TRCD_VALUE_2, \ + MEMORY_TRCD_VALUE_3 } + + +// +// TRP Memory Timing Definitions +// + +#define MEMORY_TRP_ENTRY_TYPE UINT8_TYPE +#define MEMORY_TRP_ENTRY_3 0x0 +#define MEMORY_TRP_ENTRY_2 0x1 +#define MEMORY_TRP_ENTRY_1 0x2 +#define MEMORY_TRP_ENTRY_0 0x3 + +#define MEMORY_TRP_TRANSLATION_TABLE_ENTRIES 4 +#define MEMORY_TRP_TRANSLATION_TABLE { MEMORY_TRP_ENTRY_0, \ + MEMORY_TRP_ENTRY_1, \ + MEMORY_TRP_ENTRY_2, \ + MEMORY_TRP_ENTRY_3 } + + +#define MEMORY_TRP_PRECISION 0 +#define MEMORY_TRP_VALUE_3 2 +#define MEMORY_TRP_VALUE_2 3 +#define MEMORY_TRP_VALUE_1 4 +#define MEMORY_TRP_VALUE_0 5 + +#define MEMORY_TRP_VALUES { MEMORY_TRP_VALUE_0, \ + MEMORY_TRP_VALUE_1, \ + MEMORY_TRP_VALUE_2, \ + MEMORY_TRP_VALUE_3 } + + +// +// TRAS Memory Timing Definitions +// +#define MEMORY_TRAS_MIN 4 +#define MEMORY_TRAS_MAX 18 +#define MEMORY_TRAS_STEP 1 +#define MEMORY_TRAS_DEFAULT 13 +#define MEMORY_TRAS_COUNT ((MEMORY_TRAS_MAX - MEMORY_TRAS_MIN)/MEMORY_TRAS_STEP) + 1 +#define MEMORY_TRAS_TYPE UINT8_TYPE + +// +// Uncore Multiplier Definitions +// +#define UCLK_RATIO_MIN 12 +#define UCLK_RATIO_MAX 30 +#define UCLK_RATIO_DEFAULT 20 + +#endif // #ifndef _CONFIGURATION_H diff --git a/Vlv2TbltDevicePkg/PlatformDxe/ExI.c b/Vlv2TbltDevicePkg/PlatformDxe/ExI.c new file mode 100644 index 0000000000..2dad89f606 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/ExI.c @@ -0,0 +1,83 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + ExI.c + +Abstract: + + ExI configuration based on setup option + + +--*/ + + +#include "PlatformDxe.h" + +#define PchLpcPciCfg32(Register) MmioRead32 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, Register)) + +// +// Procedure: GetPmcBase +// +// Description: This function read content of B:D:F 0:31:0, offset 44h (for +// PmcBase) +// +// Input: None +// +// Output: 32 bit PmcBase +// +UINT32 +GetPmcBase ( + VOID + ) +{ + return (PchLpcPciCfg32 (R_PCH_LPC_PMC_BASE) & B_PCH_LPC_PMC_BASE_BAR); +} + +/** + Configure ExI. + + @param ImageHandle Pointer to the loaded image protocol for this driver + @param SystemTable Pointer to the EFI System Table + + @retval EFI_SUCCESS The driver initializes correctly. +**/ +VOID +InitExI ( + ) +{ + EFI_STATUS Status; + + SYSTEM_CONFIGURATION SystemConfiguration; + UINTN VarSize; + + VarSize = sizeof(SYSTEM_CONFIGURATION); + + Status = gRT->GetVariable( + L"Setup", + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &SystemConfiguration + ); + + ASSERT_EFI_ERROR(Status); + + if (SystemConfiguration.ExISupport == 1) { + MmioOr32 ((UINTN) (GetPmcBase() + R_PCH_PMC_MTPMC1), (UINT32) BIT0+BIT1+BIT2); + } else if (SystemConfiguration.ExISupport == 0) { + MmioAnd32 ((UINTN) (GetPmcBase() + R_PCH_PMC_MTPMC1), ~((UINT32) BIT0+BIT1+BIT2)); //clear bit 0,1,2 + } +} diff --git a/Vlv2TbltDevicePkg/PlatformDxe/IchPlatformPolicy.c b/Vlv2TbltDevicePkg/PlatformDxe/IchPlatformPolicy.c new file mode 100644 index 0000000000..753eb54f22 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/IchPlatformPolicy.c @@ -0,0 +1,496 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + + This program and the accompanying materials are licensed and made available under + + the terms and conditions of the BSD License that accompanies this distribution. + + The full text of the license may be found at + + http://opensource.org/licenses/bsd-license.php. + + + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +Module Name: + + + PchPlatformPolicy.c + +Abstract: + + +--*/ + +#include "PlatformDxe.h" +#include +#include +#include + +#include "AzaliaVerbTable.h" +#include "Protocol/GlobalNvsArea.h" +#include "Protocol/DxePchPolicyUpdateProtocol.h" + +#define MOBILE_PLATFORM 1 +#define DESKTOP_PLATFORM 2 + +EFI_GUID gDxePchPolicyUpdateProtocolGuid = DXE_PCH_POLICY_UPDATE_PROTOCOL_GUID; +DXE_PCH_POLICY_UPDATE_PROTOCOL mDxePchPolicyUpdate = { 0 }; + +/** + + Updates the feature policies according to the setup variable. + + @retval VOID + +**/ +VOID +InitPchPlatformPolicy ( + IN EFI_PLATFORM_INFO_HOB *PlatformInfo + ) +{ + DXE_PCH_PLATFORM_POLICY_PROTOCOL *DxePlatformPchPolicy; + EFI_STATUS Status; + EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea; + UINT8 PortIndex; + EFI_HANDLE Handle; + PCH_STEPPING SocStepping = PchA0; + BOOLEAN ModifyVariable; + + ModifyVariable = FALSE; + DEBUG ((EFI_D_INFO, "InitPchPlatformPolicy() - Start\n")); + + Status = gBS->LocateProtocol (&gDxePchPlatformPolicyProtocolGuid, NULL, (VOID **) &DxePlatformPchPolicy); + ASSERT_EFI_ERROR (Status); + + // + // Locate the Global NVS Protocol. + // + Status = gBS->LocateProtocol ( + &gEfiGlobalNvsAreaProtocolGuid, + NULL, + (VOID **) &GlobalNvsArea + ); + ASSERT_EFI_ERROR (Status); + + // + // Update system information + // + DxePlatformPchPolicy->Revision = DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_12; + + // + // General initialization + // + DxePlatformPchPolicy->BusNumber = 0; + + // + // VLV BIOS Spec Section 3.6 Flash Security Recommendation, + // Intel strongly recommends that BIOS sets the BIOS Interface Lock Down bit. Enabling this bit + // will mitigate malicious software attempts to replace the system BIOS option ROM with its own code. + // We always enable this as a platform policy. + // + DxePlatformPchPolicy->LockDownConfig->BiosInterface = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->LockDownConfig->BiosLock = mSystemConfiguration.SpiRwProtect; + + // + // DeviceEnables + // + DxePlatformPchPolicy->DeviceEnabling->Lan = mSystemConfiguration.Lan; + DxePlatformPchPolicy->DeviceEnabling->Azalia = mSystemConfiguration.PchAzalia; + DxePlatformPchPolicy->DeviceEnabling->Sata = mSystemConfiguration.Sata; + DxePlatformPchPolicy->DeviceEnabling->Smbus = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->DeviceEnabling->LpeEnabled = mSystemConfiguration.Lpe; + + DxePlatformPchPolicy->UsbConfig->Ehci1Usbr = PCH_DEVICE_DISABLE; + + DxePlatformPchPolicy->UsbConfig->UsbXhciLpmSupport =mSystemConfiguration.UsbXhciLpmSupport; + + // + // Disable FFRD PR0 USB port2 for power saving since PR0 uses non-POR WWAN (but enable on PR0.3/PR0.5/PR1) + // + if ((PlatformInfo->BoardId == BOARD_ID_BL_FFRD) && (PlatformInfo->BoardRev == PR0)) + if (mSystemConfiguration.PchUsbPort[2] !=0) { + mSystemConfiguration.PchUsbPort[2]=0; + ModifyVariable = TRUE; + } + + + if (ModifyVariable) { + Status = gRT->SetVariable ( + NORMAL_SETUP_NAME, + &gEfiNormalSetupGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(SYSTEM_CONFIGURATION), + &mSystemConfiguration + ); + } + + SocStepping = PchStepping(); + if (mSystemConfiguration.UsbAutoMode == 1) { // auto mode is enabled + if (PchA0 == SocStepping) { + // + // For A0, EHCI is enabled as default. + // + mSystemConfiguration.PchUsb20 = 1; + mSystemConfiguration.PchUsb30Mode = 0; + mSystemConfiguration.UsbXhciSupport = 0; + DEBUG ((EFI_D_INFO, "EHCI is enabled as default. SOC 0x%x\n", SocStepping)); + } else { + // + // For A1 and later, XHCI is enabled as default. + // + mSystemConfiguration.PchUsb20 = 0; + mSystemConfiguration.PchUsb30Mode = 1; + mSystemConfiguration.UsbXhciSupport = 1; + DEBUG ((EFI_D_INFO, "XHCI is enabled as default. SOC 0x%x\n", SocStepping)); + } + // + //overwrite the setting + // + Status = gRT->SetVariable( + NORMAL_SETUP_NAME, + &gEfiNormalSetupGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(SYSTEM_CONFIGURATION), + &mSystemConfiguration + ); + } + + // + // USB Device 29 configuration + // + DxePlatformPchPolicy->UsbConfig->Usb20Settings[0].Enable = mSystemConfiguration.PchUsb20; + DxePlatformPchPolicy->UsbConfig->UsbPerPortCtl = mSystemConfiguration.PchUsbPerPortCtl; + if (mSystemConfiguration.PchUsbPerPortCtl != PCH_DEVICE_DISABLE) { + for (PortIndex = 0; PortIndex < PCH_USB_MAX_PHYSICAL_PORTS; PortIndex++) { + DxePlatformPchPolicy->UsbConfig->PortSettings[PortIndex].Enable = mSystemConfiguration.PchUsbPort[PortIndex]; + } + } + + DxePlatformPchPolicy->UsbConfig->EhciDebug = mSystemConfiguration.PchEhciDebug; + + // + // xHCI (USB 3.0) related settings from setup variable + // + DxePlatformPchPolicy->UsbConfig->Usb30Settings.XhciStreams = mSystemConfiguration.PchUsb30Streams; + + DxePlatformPchPolicy->UsbConfig->Usb30Settings.Mode = mSystemConfiguration.PchUsb30Mode; + + // + // Remove XHCI Pre-Boot Driver setup option selection from end-user view and automate loading of USB 3.0 BIOS driver based on XhciMode selection + // + switch (mSystemConfiguration.PchUsb30Mode) { + case 0: // Disabled + DxePlatformPchPolicy->UsbConfig->Usb30Settings.PreBootSupport = 0; + break; + case 1: // Enabled + DxePlatformPchPolicy->UsbConfig->Usb30Settings.PreBootSupport = 1; + break; + case 2: // Auto + DxePlatformPchPolicy->UsbConfig->Usb30Settings.PreBootSupport = 0; + break; + case 3: // Smart Auto + DxePlatformPchPolicy->UsbConfig->Usb30Settings.PreBootSupport = 1; + break; + default: + DxePlatformPchPolicy->UsbConfig->Usb30Settings.PreBootSupport = mSystemConfiguration.UsbXhciSupport; + break; + } + + + + DxePlatformPchPolicy->UsbConfig->UsbOtgSettings.Enable = mSystemConfiguration.PchUsbOtg; + + DxePlatformPchPolicy->UsbConfig->PortSettings[0].Dock = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->UsbConfig->PortSettings[1].Dock = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->UsbConfig->PortSettings[2].Dock = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->UsbConfig->PortSettings[3].Dock = PCH_DEVICE_DISABLE; + + DxePlatformPchPolicy->UsbConfig->PortSettings[0].Panel = PCH_USB_FRONT_PANEL; + DxePlatformPchPolicy->UsbConfig->PortSettings[1].Panel = PCH_USB_FRONT_PANEL; + DxePlatformPchPolicy->UsbConfig->PortSettings[2].Panel = PCH_USB_BACK_PANEL; + DxePlatformPchPolicy->UsbConfig->PortSettings[3].Panel = PCH_USB_BACK_PANEL; + + // + // + // Enable USB Topology control and program the topology setting for every USB port + // See Platform Design Guide for description of topologies + // + // + // Port 0: ~5.3", Port 1: ~4.9", Port 2: ~4.7", Port 3: ~8.0" + // + DxePlatformPchPolicy->UsbConfig->Usb20PortLength[0] = 0x53; + DxePlatformPchPolicy->UsbConfig->Usb20PortLength[1] = 0x49; + DxePlatformPchPolicy->UsbConfig->Usb20PortLength[2] = 0x47; + DxePlatformPchPolicy->UsbConfig->Usb20PortLength[3] = 0x80; + + DxePlatformPchPolicy->UsbConfig->Usb20OverCurrentPins[0] = PchUsbOverCurrentPin0; + DxePlatformPchPolicy->UsbConfig->Usb20OverCurrentPins[1] = PchUsbOverCurrentPin0; + DxePlatformPchPolicy->UsbConfig->Usb20OverCurrentPins[2] = PchUsbOverCurrentPin1; + DxePlatformPchPolicy->UsbConfig->Usb20OverCurrentPins[3] = PchUsbOverCurrentPin1; + + DxePlatformPchPolicy->UsbConfig->Usb30OverCurrentPins[0] = PchUsbOverCurrentPinSkip;//PchUsbOverCurrentPin0; + + DxePlatformPchPolicy->EhciPllCfgEnable = mSystemConfiguration.EhciPllCfgEnable; + DEBUG ((EFI_D_INFO, "InitPchPlatformPolicy() DxePlatformPchPolicy->EhciPllCfgEnable = 0x%x \n",DxePlatformPchPolicy->EhciPllCfgEnable)); + DxePlatformPchPolicy->PciExpressConfig->PcieDynamicGating = mSystemConfiguration.PcieDynamicGating; + for (PortIndex = 0; PortIndex < PCH_PCIE_MAX_ROOT_PORTS; PortIndex++) { + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].Enable = mSystemConfiguration.IchPciExp[PortIndex]; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].SlotImplemented = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].FunctionNumber = PortIndex; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].PhysicalSlotNumber = PortIndex; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].Aspm = 4; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].PmSci = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].ExtSync = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].HotPlug = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].AdvancedErrorReporting = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].UnsupportedRequestReport = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].FatalErrorReport = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].NoFatalErrorReport = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].CorrectableErrorReport = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].PmeInterrupt = 0; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].SystemErrorOnFatalError = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].SystemErrorOnNonFatalError = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].SystemErrorOnCorrectableError = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->PciExpressConfig->RootPort[PortIndex].CompletionTimeout = PchPciECompletionTO_Default; + } + + // + // SATA configuration + // + for (PortIndex = 0; PortIndex < PCH_AHCI_MAX_PORTS; PortIndex++) { + if (mSystemConfiguration.SataType == 0) { + DxePlatformPchPolicy->SataConfig->PortSettings[PortIndex].Enable = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->SataConfig->LegacyMode = PCH_DEVICE_ENABLE; + } else { + DxePlatformPchPolicy->SataConfig->PortSettings[PortIndex].Enable = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->SataConfig->LegacyMode = PCH_DEVICE_DISABLE; + } + if(mSystemConfiguration.Sata == 1){ + DxePlatformPchPolicy->SataConfig->PortSettings[PortIndex].Enable = PCH_DEVICE_ENABLE; + } else { + DxePlatformPchPolicy->SataConfig->PortSettings[PortIndex].Enable = PCH_DEVICE_DISABLE; + } + if(0 == PortIndex){ + DxePlatformPchPolicy->SataConfig->PortSettings[PortIndex].HotPlug = PCH_DEVICE_DISABLE; + } else if(1 == PortIndex){ + DxePlatformPchPolicy->SataConfig->PortSettings[PortIndex].HotPlug = PCH_DEVICE_DISABLE; + } + + DxePlatformPchPolicy->SataConfig->PortSettings[PortIndex].SpinUp = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->SataConfig->PortSettings[PortIndex].MechSw = PCH_DEVICE_DISABLE; + } + DxePlatformPchPolicy->SataConfig->RaidAlternateId = PCH_DEVICE_DISABLE; + DxePlatformPchPolicy->SataConfig->Raid0 = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->SataConfig->Raid1 = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->SataConfig->Raid10 = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->SataConfig->Raid5 = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->SataConfig->Irrt = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->SataConfig->OromUiBanner = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->SataConfig->HddUnlock = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->SataConfig->LedLocate = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->SataConfig->IrrtOnly = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->SataConfig->SalpSupport = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->SataConfig->TestMode = mSystemConfiguration.SataTestMode; + + // + // AzaliaConfig + // + DxePlatformPchPolicy->AzaliaConfig->Pme = mSystemConfiguration.AzaliaPme; + DxePlatformPchPolicy->AzaliaConfig->HdmiCodec = mSystemConfiguration.HdmiCodec; + DxePlatformPchPolicy->AzaliaConfig->DS = mSystemConfiguration.AzaliaDs; + DxePlatformPchPolicy->AzaliaConfig->AzaliaVCi = mSystemConfiguration.AzaliaVCiEnable; + + // + // Set LPSS configuration according to setup value. + // + DxePlatformPchPolicy->LpssConfig->LpssPciModeEnabled = mSystemConfiguration.LpssPciModeEnabled; + + DxePlatformPchPolicy->LpssConfig->Dma1Enabled = mSystemConfiguration.LpssDma1Enabled; + DxePlatformPchPolicy->LpssConfig->I2C0Enabled = mSystemConfiguration.LpssI2C0Enabled; + DxePlatformPchPolicy->LpssConfig->I2C1Enabled = mSystemConfiguration.LpssI2C1Enabled; + DxePlatformPchPolicy->LpssConfig->I2C2Enabled = mSystemConfiguration.LpssI2C2Enabled; + DxePlatformPchPolicy->LpssConfig->I2C3Enabled = mSystemConfiguration.LpssI2C3Enabled; + DxePlatformPchPolicy->LpssConfig->I2C4Enabled = mSystemConfiguration.LpssI2C4Enabled; + DxePlatformPchPolicy->LpssConfig->I2C5Enabled = mSystemConfiguration.LpssI2C5Enabled; + DxePlatformPchPolicy->LpssConfig->I2C6Enabled = mSystemConfiguration.LpssI2C6Enabled; + + DxePlatformPchPolicy->LpssConfig->Dma0Enabled = mSystemConfiguration.LpssDma0Enabled;; + DxePlatformPchPolicy->LpssConfig->Pwm0Enabled = mSystemConfiguration.LpssPwm0Enabled; + DxePlatformPchPolicy->LpssConfig->Pwm1Enabled = mSystemConfiguration.LpssPwm1Enabled; + DxePlatformPchPolicy->LpssConfig->Hsuart0Enabled = mSystemConfiguration.LpssHsuart0Enabled; + DxePlatformPchPolicy->LpssConfig->Hsuart1Enabled = mSystemConfiguration.LpssHsuart1Enabled; + DxePlatformPchPolicy->LpssConfig->SpiEnabled = mSystemConfiguration.LpssSpiEnabled; + + // + // Set SCC configuration according to setup value. + // + DxePlatformPchPolicy->SccConfig->SdioEnabled = mSystemConfiguration.LpssSdioEnabled; + DxePlatformPchPolicy->SccConfig->SdcardEnabled = TRUE; + DxePlatformPchPolicy->SccConfig->SdCardSDR25Enabled = mSystemConfiguration.LpssSdCardSDR25Enabled; + DxePlatformPchPolicy->SccConfig->SdCardDDR50Enabled = mSystemConfiguration.LpssSdCardDDR50Enabled; + DxePlatformPchPolicy->SccConfig->HsiEnabled = mSystemConfiguration.LpssMipiHsi; + + if (mSystemConfiguration.eMMCBootMode== 1) {// Auto detection mode + // + // Silicon Stepping + // + switch (PchStepping()) { + case PchA0: // A0 and A1 + case PchA1: + DEBUG ((EFI_D_ERROR, "Auto Detect: SOC A0/A1: SCC eMMC 4.41 Configuration\n")); + DxePlatformPchPolicy->SccConfig->eMMCEnabled = 1; + DxePlatformPchPolicy->SccConfig->eMMC45Enabled = 0; + DxePlatformPchPolicy->SccConfig->eMMC45DDR50Enabled = 0; + DxePlatformPchPolicy->SccConfig->eMMC45HS200Enabled = 0; + DxePlatformPchPolicy->SccConfig->eMMC45RetuneTimerValue = 0; + break; + case PchB0: // B0 and later + default: + DEBUG ((EFI_D_ERROR, "Auto Detect: SOC B0 and later: SCC eMMC 4.5 Configuration\n")); + DxePlatformPchPolicy->SccConfig->eMMCEnabled = 0; + DxePlatformPchPolicy->SccConfig->eMMC45Enabled = mSystemConfiguration.LpsseMMC45Enabled; + DxePlatformPchPolicy->SccConfig->eMMC45DDR50Enabled = mSystemConfiguration.LpsseMMC45DDR50Enabled; + DxePlatformPchPolicy->SccConfig->eMMC45HS200Enabled = mSystemConfiguration.LpsseMMC45HS200Enabled; + DxePlatformPchPolicy->SccConfig->eMMC45RetuneTimerValue = mSystemConfiguration.LpsseMMC45RetuneTimerValue; + break; + } + } else if (mSystemConfiguration.eMMCBootMode == 2) { // eMMC 4.41 + DEBUG ((EFI_D_ERROR, "Force to SCC eMMC 4.41 Configuration\n")); + DxePlatformPchPolicy->SccConfig->eMMCEnabled = 1; + DxePlatformPchPolicy->SccConfig->eMMC45Enabled = 0; + DxePlatformPchPolicy->SccConfig->eMMC45DDR50Enabled = 0; + DxePlatformPchPolicy->SccConfig->eMMC45HS200Enabled = 0; + DxePlatformPchPolicy->SccConfig->eMMC45RetuneTimerValue = 0; + + } else if (mSystemConfiguration.eMMCBootMode == 3) { // eMMC 4.5 + DEBUG ((EFI_D_ERROR, "Force to eMMC 4.5 Configuration\n")); + DxePlatformPchPolicy->SccConfig->eMMCEnabled = 0; + DxePlatformPchPolicy->SccConfig->eMMC45Enabled = mSystemConfiguration.LpsseMMC45Enabled; + DxePlatformPchPolicy->SccConfig->eMMC45DDR50Enabled = mSystemConfiguration.LpsseMMC45DDR50Enabled; + DxePlatformPchPolicy->SccConfig->eMMC45HS200Enabled = mSystemConfiguration.LpsseMMC45HS200Enabled; + DxePlatformPchPolicy->SccConfig->eMMC45RetuneTimerValue = mSystemConfiguration.LpsseMMC45RetuneTimerValue; + + } else { // Disable eMMC controllers + DEBUG ((EFI_D_ERROR, "Disable eMMC controllers\n")); + DxePlatformPchPolicy->SccConfig->eMMCEnabled = 0; + DxePlatformPchPolicy->SccConfig->eMMC45Enabled = 0; + DxePlatformPchPolicy->SccConfig->eMMC45DDR50Enabled = 0; + DxePlatformPchPolicy->SccConfig->eMMC45HS200Enabled = 0; + DxePlatformPchPolicy->SccConfig->eMMC45RetuneTimerValue = 0; + } + + // + // Reserved SMBus Address + // + DxePlatformPchPolicy->SmbusConfig->NumRsvdSmbusAddresses = 4; + DxePlatformPchPolicy->SmbusConfig->RsvdSmbusAddressTable = mSmbusRsvdAddresses; + + // + // MiscPm Configuration + // + DxePlatformPchPolicy->MiscPmConfig->WakeConfig.WolEnableOverride = mSystemConfiguration.WakeOnLanS5; + DxePlatformPchPolicy->MiscPmConfig->SlpLanLowDc = mSystemConfiguration.SlpLanLowDc; + DxePlatformPchPolicy->MiscPmConfig->PowerResetStatusClear.MeWakeSts = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->MiscPmConfig->PowerResetStatusClear.MeHrstColdSts = PCH_DEVICE_ENABLE; + DxePlatformPchPolicy->MiscPmConfig->PowerResetStatusClear.MeHrstWarmSts = PCH_DEVICE_ENABLE; + + // + // Enable / disable serial IRQ according to setup value. + // + DxePlatformPchPolicy->SerialIrqConfig->SirqEnable = PCH_DEVICE_ENABLE; + + // + // Set Serial IRQ Mode Select according to setup value. + // + DxePlatformPchPolicy->SerialIrqConfig->SirqMode = PchQuietMode; + + // + // Program the default Sub System Vendor Device Id + // + DxePlatformPchPolicy->DefaultSvidSid->SubSystemVendorId = V_PCH_INTEL_VENDOR_ID; + DxePlatformPchPolicy->DefaultSvidSid->SubSystemId = V_PCH_DEFAULT_SID; + + mAzaliaVerbTable[9].VerbTableData = mAzaliaVerbTableData12; + + DxePlatformPchPolicy->AzaliaConfig->AzaliaVerbTableNum = sizeof (mAzaliaVerbTable) / sizeof (PCH_AZALIA_VERB_TABLE); + DxePlatformPchPolicy->AzaliaConfig->AzaliaVerbTable = mAzaliaVerbTable; + DxePlatformPchPolicy->AzaliaConfig->ResetWaitTimer = 300; + + DxePlatformPchPolicy->IdleReserve = mSystemConfiguration.IdleReserve; + DxePlatformPchPolicy->AcpiHWRed = PCH_DEVICE_DISABLE; + + // + // Install DxePchPolicyUpdateProtocol + // + Handle = NULL; + + mDxePchPolicyUpdate.Revision = DXE_PCH_POLICY_UPDATE_PROTOCOL_REVISION_1; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gDxePchPolicyUpdateProtocolGuid, + &mDxePchPolicyUpdate, + NULL + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "InitPchPlatformPolicy() - End\n")); +} + + +DXE_VLV_PLATFORM_POLICY_PROTOCOL mDxePlatformVlvPolicy; + +VOID +InitVlvPlatformPolicy ( + ) +{ + DXE_VLV_PLATFORM_POLICY_PROTOCOL *DxePlatformVlvPolicy; + EFI_STATUS Status; + EFI_HANDLE Handle; + + ZeroMem (&mDxePlatformVlvPolicy, sizeof(DXE_VLV_PLATFORM_POLICY_PROTOCOL)); + + DxePlatformVlvPolicy = &mDxePlatformVlvPolicy; + + + DxePlatformVlvPolicy->GraphicReserve00 = mSystemConfiguration.GraphicReserve00; + DxePlatformVlvPolicy->PavpMode = mSystemConfiguration.PavpMode; + DxePlatformVlvPolicy->GraphicReserve01 = 1; + DxePlatformVlvPolicy->GraphicReserve02 = mSystemConfiguration.GraphicReserve02; + DxePlatformVlvPolicy->GraphicReserve03 = 1; + DxePlatformVlvPolicy->GraphicReserve04 = 0; + DxePlatformVlvPolicy->GraphicReserve05 = mSystemConfiguration.GraphicReserve05; + DxePlatformVlvPolicy->IgdPanelFeatures.PFITStatus = mSystemConfiguration.PanelScaling; + + DxePlatformVlvPolicy->IgdPanelFeatures.LidStatus = 1; + DxePlatformVlvPolicy->IdleReserve = mSystemConfiguration.IdleReserve; + + DxePlatformVlvPolicy->GraphicReserve06 = 1; + + if ( (mSystemConfiguration.Lpe == 1) || mSystemConfiguration.Lpe == 2) { + DxePlatformVlvPolicy ->AudioTypeSupport = LPE_AUDIO ; + } else if ( mSystemConfiguration.PchAzalia == 1 ) { + DxePlatformVlvPolicy ->AudioTypeSupport = HD_AUDIO; + } else { + DxePlatformVlvPolicy ->AudioTypeSupport = NO_AUDIO; + } + + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gDxeVlvPlatformPolicyGuid, + EFI_NATIVE_INTERFACE, + DxePlatformVlvPolicy + ); + ASSERT_EFI_ERROR(Status); + +} diff --git a/Vlv2TbltDevicePkg/PlatformDxe/IchRegTable.c b/Vlv2TbltDevicePkg/PlatformDxe/IchRegTable.c new file mode 100644 index 0000000000..06d325c39e --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/IchRegTable.c @@ -0,0 +1,141 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + IchRegTable.c + +Abstract: + + Register initialization table for Ich. + + + +--*/ + +#include +#include "PlatformDxe.h" +extern EFI_PLATFORM_INFO_HOB mPlatformInfo; + +#define R_EFI_PCI_SVID 0x2C + +EFI_REG_TABLE mSubsystemIdRegs [] = { + + // + // Program SVID and SID for PCI devices. + // Combine two 16 bit PCI_WRITE into one 32 bit PCI_WRITE in order to boost performance + // + PCI_WRITE ( + MC_BUS, MC_DEV, MC_FUN, R_EFI_PCI_SVID, EfiPciWidthUint32, + V_PCH_DEFAULT_SVID_SID, OPCODE_FLAG_S3SAVE + ), + + PCI_WRITE ( + IGD_BUS, IGD_DEV, IGD_FUN_0, R_EFI_PCI_SVID, EfiPciWidthUint32, + V_PCH_DEFAULT_SVID_SID, OPCODE_FLAG_S3SAVE + ), + + PCI_WRITE( + DEFAULT_PCI_BUS_NUMBER_PCH, 0, 0, R_EFI_PCI_SVID, EfiPciWidthUint32, + V_PCH_DEFAULT_SVID_SID, OPCODE_FLAG_S3SAVE + ), + PCI_WRITE ( + DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, PCI_FUNCTION_NUMBER_PCH_LPC, R_PCH_LPC_SS, EfiPciWidthUint32, + V_PCH_DEFAULT_SVID_SID, OPCODE_FLAG_S3SAVE + ), + PCI_WRITE ( + DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SATA, PCI_FUNCTION_NUMBER_PCH_SATA, R_PCH_SATA_SS, EfiPciWidthUint32, + V_PCH_DEFAULT_SVID_SID, OPCODE_FLAG_S3SAVE + ), + PCI_WRITE ( + DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SMBUS, PCI_FUNCTION_NUMBER_PCH_SMBUS, R_PCH_SMBUS_SVID, EfiPciWidthUint32, + V_PCH_DEFAULT_SVID_SID, OPCODE_FLAG_S3SAVE + ), + PCI_WRITE ( + DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_USB, PCI_FUNCTION_NUMBER_PCH_EHCI, R_PCH_EHCI_SVID, EfiPciWidthUint32, + V_PCH_DEFAULT_SVID_SID, OPCODE_FLAG_S3SAVE + ), + PCI_WRITE ( + DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1, R_PCH_PCIE_SVID, EfiPciWidthUint32, + V_PCH_DEFAULT_SVID_SID, OPCODE_FLAG_S3SAVE + ), + PCI_WRITE ( + DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2, R_PCH_PCIE_SVID, EfiPciWidthUint32, + V_PCH_DEFAULT_SVID_SID, OPCODE_FLAG_S3SAVE + ), + PCI_WRITE ( + DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3, R_PCH_PCIE_SVID, EfiPciWidthUint32, + V_PCH_DEFAULT_SVID_SID, OPCODE_FLAG_S3SAVE + ), + PCI_WRITE ( + DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4, R_PCH_PCIE_SVID, EfiPciWidthUint32, + V_PCH_DEFAULT_SVID_SID, OPCODE_FLAG_S3SAVE + ), + TERMINATE_TABLE +}; + +/** + Updates the mSubsystemIdRegs table, and processes it. This should program + the Subsystem Vendor and Device IDs. + + @retval Returns VOID + +**/ +VOID +InitializeSubsystemIds ( + ) +{ + + EFI_REG_TABLE *RegTablePtr; + UINT32 SubsystemVidDid; + UINT32 SubsystemAudioVidDid; + + SubsystemVidDid = mPlatformInfo.SsidSvid; + SubsystemAudioVidDid = mPlatformInfo.SsidSvid; + + RegTablePtr = mSubsystemIdRegs; + + // + // While we are not at the end of the table + // + while (RegTablePtr->Generic.OpCode != OP_TERMINATE_TABLE) { + // + // If the data to write is the original SSID + // + if (RegTablePtr->PciWrite.Data == + ((V_PCH_DEFAULT_SID << 16) | + V_PCH_INTEL_VENDOR_ID) + ) { + + // + // Then overwrite it to use the alternate SSID + // + RegTablePtr->PciWrite.Data = SubsystemVidDid; + } + + // + // Go to next table entry + // + RegTablePtr++; + } + + RegTablePtr = mSubsystemIdRegs; + + + // + // Program the SSVID/SSDID + // + ProcessRegTablePci (mSubsystemIdRegs, mPciRootBridgeIo, NULL); + +} diff --git a/Vlv2TbltDevicePkg/PlatformDxe/IchTcoReset.c b/Vlv2TbltDevicePkg/PlatformDxe/IchTcoReset.c new file mode 100644 index 0000000000..7c21271a09 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/IchTcoReset.c @@ -0,0 +1,216 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + IchTcoReset.c + +Abstract: + Implements the programming of events in TCO Reset + + +--*/ + +#include "PlatformDxe.h" +#include +#include + + +EFI_STATUS +EFIAPI +EnableTcoReset ( + IN UINT32 *RcrbGcsSaveValue + ); + +EFI_STATUS +EFIAPI +DisableTcoReset ( + OUT UINT32 RcrbGcsRestoreValue + ); + +EFI_TCO_RESET_PROTOCOL mTcoResetProtocol = { + EnableTcoReset, + DisableTcoReset +}; + +/** + + Enables the TCO timer to reset the system in case of a system hang. This is + used when writing the clock registers. + + @param RcrbGcsSaveValue This is the value of the RCRB GCS register before it is + changed by this procedure. This will be used to restore + the settings of this register in PpiDisableTcoReset. + + @retval EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +EnableTcoReset ( + IN UINT32 *RcrbGcsSaveValue + ) +{ + UINT16 TmpWord; + UINT16 AcpiBase; + EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL *WatchdogTimerProtocol; + EFI_STATUS Status; + UINTN PbtnDisableInterval = 4; //Default value + + // + // Get Watchdog Timer protocol. + // + Status = gBS->LocateProtocol ( + &gEfiWatchdogTimerDriverProtocolGuid, + NULL, + (VOID **)&WatchdogTimerProtocol + ); + + // + // If the protocol is present, shut off the Timer as we enter BDS + // + if (!EFI_ERROR(Status)) { + WatchdogTimerProtocol->RestartWatchdogTimer(); + WatchdogTimerProtocol->AllowKnownReset(TRUE); + } + + if (*RcrbGcsSaveValue == 0) { + PbtnDisableInterval = PcdGet32(PcdPBTNDisableInterval); + } else { + PbtnDisableInterval = *RcrbGcsSaveValue * 10 / 6; + } + + // + // Read ACPI Base Address + // + AcpiBase = PchLpcPciCfg16(R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR; + + // + // Stop TCO if not already stopped + // + TmpWord = IoRead16(AcpiBase + R_PCH_TCO_CNT); + TmpWord |= B_PCH_TCO_CNT_TMR_HLT; + IoWrite16(AcpiBase + R_PCH_TCO_CNT, TmpWord); + + // + // Clear second TCO status + // + IoWrite32(AcpiBase + R_PCH_TCO_STS, B_PCH_TCO_STS_SECOND_TO); + + // + // Enable reboot on TCO timeout + // + *RcrbGcsSaveValue = MmioRead32 (PMC_BASE_ADDRESS + R_PCH_PMC_PM_CFG); + MmioAnd8 (PMC_BASE_ADDRESS + R_PCH_PMC_PM_CFG, (UINT8) ~B_PCH_PMC_PM_CFG_NO_REBOOT); + + // + // Set TCO reload value (interval *.6s) + // + IoWrite32(AcpiBase + R_PCH_TCO_TMR, (UINT32)(PbtnDisableInterval<<16)); + + // + // Force TCO to load new value + // + IoWrite8(AcpiBase + R_PCH_TCO_RLD, 4); + + // + // Clear second TCO status + // + IoWrite32(AcpiBase + R_PCH_TCO_STS, B_PCH_TCO_STS_SECOND_TO); + + // + // Start TCO timer running + // + TmpWord = IoRead16(AcpiBase + R_PCH_TCO_CNT); + TmpWord &= ~(B_PCH_TCO_CNT_TMR_HLT); + IoWrite16(AcpiBase + R_PCH_TCO_CNT, TmpWord); + + return EFI_SUCCESS; +} + +/** + Disables the TCO timer. This is used after writing the clock registers. + + @param RcrbGcsRestoreValue Value saved in PpiEnableTcoReset so that it can + restored. + + @retval EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +DisableTcoReset ( + OUT UINT32 RcrbGcsRestoreValue + ) +{ + UINT16 TmpWord; + UINT16 AcpiBase; + EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL *WatchdogTimerProtocol; + EFI_STATUS Status; + + // + // Read ACPI Base Address + // + AcpiBase = PchLpcPciCfg16(R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR; + + // + // Stop the TCO timer + // + TmpWord = IoRead16(AcpiBase + R_PCH_TCO_CNT); + TmpWord |= B_PCH_TCO_CNT_TMR_HLT; + IoWrite16(AcpiBase + R_PCH_TCO_CNT, TmpWord); + + // + // Get Watchdog Timer protocol. + // + Status = gBS->LocateProtocol ( + &gEfiWatchdogTimerDriverProtocolGuid, + NULL, + (VOID **)&WatchdogTimerProtocol + ); + + // + // If the protocol is present, shut off the Timer as we enter BDS + // + if (!EFI_ERROR(Status)) { + WatchdogTimerProtocol->AllowKnownReset(FALSE); + } + + return EFI_SUCCESS; +} + +/** + + Updates the feature policies according to the setup variable. + + @retval Returns VOID + +**/ +VOID +InitTcoReset ( + ) +{ + EFI_HANDLE Handle; + EFI_STATUS Status; + + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiTcoResetProtocolGuid, + EFI_NATIVE_INTERFACE, + &mTcoResetProtocol + ); + ASSERT_EFI_ERROR(Status); + +} diff --git a/Vlv2TbltDevicePkg/PlatformDxe/IdccInfo.c b/Vlv2TbltDevicePkg/PlatformDxe/IdccInfo.c new file mode 100644 index 0000000000..69932223bd --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/IdccInfo.c @@ -0,0 +1,77 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + IdccInfo.c + +Abstract: + + Platform information used by IDCC. + +Revision History + +--*/ + +#include "PlatformDxe.h" + +#include + +extern EFI_GUID mPlatformDriverGuid; + + +EFI_STATUS +WriteIdccInfo ( + ) +{ + EFI_STATUS Status; + EFI_DATA_HUB_PROTOCOL *DataHub; + UINT8 Ratio; + EFI_IDCC_PROCESSOR_RATIO ProcRatio; + + // + // Locate the data hub protocol + // + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + (VOID **) &DataHub + ); + + // + // Find processor actual ratio + // + Ratio = 15; //Temporary - some dummy value. + + // + // Fill in IDCC Type 5 structure + // + ProcRatio.IdccHeader.Type = EFI_IDCC_PROC_RATIO_TYPE; + ProcRatio.IdccHeader.RecordLength = sizeof(EFI_IDCC_PROCESSOR_RATIO); + ProcRatio.ProcessorRatio = Ratio; + + // + // Write data to the data hub + // + Status = DataHub->LogData ( + DataHub, + &gIdccDataHubGuid, + &mPlatformDriverGuid, + EFI_DATA_RECORD_CLASS_DATA, + &ProcRatio, + sizeof(EFI_IDCC_PROCESSOR_RATIO) + ); + + return Status; +} diff --git a/Vlv2TbltDevicePkg/PlatformDxe/LegacySpeaker.c b/Vlv2TbltDevicePkg/PlatformDxe/LegacySpeaker.c new file mode 100644 index 0000000000..9ac816dd40 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/LegacySpeaker.c @@ -0,0 +1,166 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + LegacySpeaker.c + +Abstract: + + This file implements DXE for Legacy Speaker. + +--*/ + +#include "LegacySpeaker.h" + +/** + + This function will enable the speaker to generate beep + + @retval EFI_STATUS + +**/ +EFI_STATUS +TurnOnSpeaker ( + ) +{ + UINT8 Data; + Data = IoRead8 (EFI_SPEAKER_CONTROL_PORT); + Data |= 0x03; + IoWrite8(EFI_SPEAKER_CONTROL_PORT, Data); + return EFI_SUCCESS; +} + +/** + + This function will stop beep from speaker. + + @retval Status + +**/ +EFI_STATUS +TurnOffSpeaker ( + ) +{ + UINT8 Data; + + Data = IoRead8 (EFI_SPEAKER_CONTROL_PORT); + Data &= 0xFC; + IoWrite8(EFI_SPEAKER_CONTROL_PORT, Data); + return EFI_SUCCESS; +} + +/** + Generate beep sound based upon number of beeps and duration of the beep + + @param NumberOfBeeps Number of beeps which user want to produce + @param BeepDuration Duration for speaker gate need to be enabled + @param TimeInterval Interval between each beep + + @retval Does not return if the reset takes place. + EFI_INVALID_PARAMETER If ResetType is invalid. + +**/ +EFI_STATUS +OutputBeep ( + IN UINTN NumberOfBeep, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ) +{ + UINTN Num; + + for (Num=0; Num < NumberOfBeep; Num++) { + TurnOnSpeaker (); + // + // wait some time,at least 120us + // + gBS->Stall (BeepDuration); + TurnOffSpeaker(); + gBS->Stall (TimeInterval); + } + + return EFI_SUCCESS; +} + +/** + This function will program the speaker tone frequency. The value should be with 64k + boundary since it takes only 16 bit value which gets programmed in two step IO opearattion + + @param Frequency A value which should be 16 bit only. + + @retval EFI_SUCESS + +**/ +EFI_STATUS +EFIAPI +ProgramToneFrequency ( + IN EFI_SPEAKER_IF_PROTOCOL * This, + IN UINT16 Frequency + ) +{ + UINT8 Data; + + Data = 0xB6; + IoWrite8(EFI_TIMER_CONTROL_PORT, Data); + + Data = (UINT8)(Frequency & 0x00FF); + IoWrite8(EFI_TIMER_2_PORT, Data); + Data = (UINT8)((Frequency & 0xFF00) >> 8); + IoWrite8(EFI_TIMER_2_PORT, Data); + return EFI_SUCCESS; +} + +/** + This function will generate the beep for specified duration. + + @param NumberOfBeeps Number of beeps which user want to produce + @param BeepDuration Duration for speaker gate need to be enabled + @param TimeInterval Interval between each beep + + @retval EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +GenerateBeepTone ( + IN EFI_SPEAKER_IF_PROTOCOL * This, + IN UINTN NumberOfBeeps, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ) +{ + + if ((NumberOfBeeps == 1) && (BeepDuration == 0) && (TimeInterval == 0)) { + TurnOnSpeaker (); + return EFI_SUCCESS; + } + + if ((NumberOfBeeps == 0) && (BeepDuration == 0) && (TimeInterval == 0)) { + TurnOffSpeaker (); + return EFI_SUCCESS; + } + + if (BeepDuration == 0) { + BeepDuration = EFI_DEFAULT_SHORT_BEEP_DURATION; + } + + if (TimeInterval == 0) { + TimeInterval = EFI_DEFAULT_BEEP_TIME_INTERVAL; + } + + OutputBeep (NumberOfBeeps, BeepDuration, TimeInterval); + return EFI_SUCCESS; + + +} diff --git a/Vlv2TbltDevicePkg/PlatformDxe/LegacySpeaker.h b/Vlv2TbltDevicePkg/PlatformDxe/LegacySpeaker.h new file mode 100644 index 0000000000..2075139195 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/LegacySpeaker.h @@ -0,0 +1,74 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + LegacySpeaker.h + +Abstract: + + Speaker enabling related data + +--*/ + +#ifndef _DXE_LEGACY_SPEAKER_H +#define _DXE_LEGACY_SPEAKER_H + +#include "PlatformDxe.h" + +// +// Speaker Related Port Information +// +#define EFI_TIMER_COUNTER_PORT 0x40 +#define EFI_TIMER_CONTROL_PORT 0x43 +#define EFI_TIMER_2_PORT 0x42 +#define EFI_SPEAKER_CONTROL_PORT 0x61 + +#define EFI_SPEAKER_OFF_MASK 0xFC + +#define EFI_DEFAULT_BEEP_FREQUENCY 0x500 + +// +// Default Intervals/Beep Duration +// +#define EFI_DEFAULT_LONG_BEEP_DURATION 0x70000 +#define EFI_DEFAULT_SHORT_BEEP_DURATION 0x50000 +#define EFI_DEFAULT_BEEP_TIME_INTERVAL 0x20000 + + +EFI_STATUS +EFIAPI +ProgramToneFrequency ( + IN EFI_SPEAKER_IF_PROTOCOL * This, + IN UINT16 Frequency + ); + + +EFI_STATUS +EFIAPI +GenerateBeepTone ( + IN EFI_SPEAKER_IF_PROTOCOL * This, + IN UINTN NumberOfBeeps, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ); + +EFI_STATUS +TurnOnSpeaker ( + ); + +EFI_STATUS +TurnOffSpeaker ( + ); + +#endif diff --git a/Vlv2TbltDevicePkg/PlatformDxe/Observable/Observable.c b/Vlv2TbltDevicePkg/PlatformDxe/Observable/Observable.c new file mode 100644 index 0000000000..c67862c081 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/Observable/Observable.c @@ -0,0 +1,587 @@ +/*++ + This file contains 'Framework Code' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may not be modified, except as allowed by + additional terms of your license agreement. +--*/ +/*++ + +Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Observable.c + +Abstract: + + The following contains all of the implementation for the Observable protocol. The + protocol uses the observer design pattern to provide a way to publish events and + to subscribe to those events so that a callback will be performed at the time of + the event. The observables and subscribers are maintained by the static tree, + mObservableDb. The difference between this protocol and the existing event protocol + that exists within the EFI framework is that this protocol allows for parameters + to be passed to the subscribed callbacks that can contain up to date context. + +--*/ + +#include "Observable.h" + +static OBS_TREE* mObservableDb = NULL; +static EFI_HANDLE mObservableHandle = NULL; +static OBS_OBSERVABLE_PROTOCOL mObservable = { + AddObservable, + RemoveObservable, + Subscribe, + Unsubscribe, + Publish, + RemoveAllObservables +}; + +/** Install observable protocol. + * + * Install interface and initialize the observable protocol. + * + * @param VOID No parameters. + * + * @return EFI_SUCCESS Successfully installed and initialized the protocol. + **/ +EFI_STATUS +InitializeObservableProtocol( + VOID + ) +{ + EFI_STATUS Status; + + // + // Install protocol. + // + Status = gBS->InstallProtocolInterface ( + &mObservableHandle, + &gObservableProtocolGuid, + EFI_NATIVE_INTERFACE, + &mObservable + ); + + return Status; +} + +/** Deletes a subscriber + * + * This function removes the subscriber pointed to by Head. + * + * @param OBS_TREE* Head Points to the current subscriber. + * + * @return OBS_TREE* Returns the tree after successfully removing the subscriber. + **/ +OBS_LEAF* +DeleteSubscriber( + OBS_LEAF* Head + ) +{ + OBS_LEAF* Temp; + + if (Head) { + Temp = Head; + Head = Head->Next; + gBS->FreePool(Temp); + } + + return Head; +} + +/** Finds and deletes all subscribers + * + * This function iterates recursively through the existing subscribers and delets them all. + * + * @param OBS_TREE* Head Points to the current subscriber. + * + * @return OBS_TREE* Returns the tree after successfully removing the subscribers. + **/ +OBS_LEAF* +DeleteAllSubscribers( + OBS_LEAF* Head + ) +{ + if (Head) { + if (Head->Next) { + // + // We aren't at the end of the list yet. + // + Head->Next = DeleteAllSubscribers(Head->Next); + } + + // + // At the end, so delete the subscriber. + // + Head = DeleteSubscriber(Head); + } + + return Head; +} + +/** Deletes an observable + * + * This function removes the observable pointed to by Head. + * + * @param OBS_TREE* Head Points to the current observable. + * + * @return OBS_TREE* Returns the tree after successfully removing the observable. + **/ +OBS_TREE* +DeleteObservable( + OBS_TREE* Head + ) +{ + OBS_TREE* Temp; + + if (Head) { + Temp = Head; + Head = Head->Next; + gBS->FreePool(Temp); + } + + return Head; +} + +/** Finds and deletes all observables + * + * This function iterates recursively through the existing observables database and, starting with + * the last most observable, deletes all of its subscribers, then deletes the observable itself. + * + * @param OBS_TREE* Head Points to the current observable. + * + * @return OBS_TREE* Returns the tree after successfully removing the observables. + **/ +OBS_TREE* +DeleteAllObservables( + OBS_TREE* Head + ) +{ + if (Head) { + if (Head->Next) { + // + // We aren't at the end of the list yet. + // + Head->Next = DeleteAllObservables(Head->Next); + } + + // + // This is the end of the list of observables. + // + Head->Leaf = DeleteAllSubscribers(Head->Leaf); + + // + // Subscribers are deleted, so now delete the observable. + // + Head = DeleteObservable(Head); + } + + return Head; +} + +/** Finds and deletes observable + * + * This function iterates recursively through the existing observable database in order to find the one + * specified by ReferenceGuid so that it can be deleted. If the requested observable is found, before it + * is deleted, all of the subscribers that are listening to this observable are deleted. + * + * @param OBS_TREE* Head Points to the current observable. + * EFI_GUID ReferenceGuid Corresponds to the observable that we're looking for. + * + * @return OBS_TREE* Returns the tree after successfully removing (or not finding) the observable. + **/ +OBS_TREE* +FindAndDeleteObservable( + OBS_TREE* Head, + EFI_GUID ReferenceGuid + ) +{ + if (Head) { + if (CompareMem(&(Head->ObservableGuid), &ReferenceGuid, sizeof(ReferenceGuid)) == 0) { + // + // We found the observable. Delete all of it's subscribers, first. + // + Head->Leaf = DeleteAllSubscribers(Head->Leaf); + // + // Now we can safely remove the observable. + // + Head = DeleteObservable(Head); + } else { + // + // Not found. Keep searching. + // + Head->Next = FindAndDeleteObservable(Head->Next, ReferenceGuid); + } + } + + return Head; +} + +/** Finds and deletes subscriber + * + * This function iterates recursively through the existing subscribers that are listening to the + * observable that was found when this function was called. + * + * @param OBS_TREE* Head Points to the current subscriber. + * OBS_CALLBACK CallbackInterface This is the subscriber that is requested be removed. + * + * @return OBS_TREE* Returns the tree after successfully removing (or not finding) the subscriber. + **/ +OBS_LEAF* +_FindAndDeleteSubscriber( + OBS_LEAF* Head, + OBS_CALLBACK CallbackInterface + ) +{ + if (Head) { + if (Head->Observer == CallbackInterface) { + // + // Found it. Now let's delete it. + // + Head = DeleteSubscriber(Head); + } else { + // + // Not found. Keep searching. + // + Head->Next = _FindAndDeleteSubscriber(Head->Next, CallbackInterface); + } + } + + return Head; +} + +/** Finds and deletes subscriber + * + * This function iterates recursively through the existing observables database until it either finds + * a matching guid or reaches the end of the list. After finding a match, it calls a helper function, + * _FindAndDeleteSubscriber. At this point, all responsibility for finding and deleting the subscriber + * lies on the helper function. + * + * @param OBS_TREE* Head Points to the current observable. + * EFI_GUID ReferenceGuid Corresponds to the observable that we're looking for. + * OBS_CALLBACK CallbackInterface This is the subscriber that is requested be removed. + * + * @return OBS_TREE* Returns the tree after successfully removing (or not finding) the subscriber. + **/ +OBS_TREE* +FindAndDeleteSubscriber( + IN OUT OBS_TREE* Head, + IN EFI_GUID ReferenceGuid, + IN OBS_CALLBACK CallbackInterface + ) +{ + if (Head) { + if (CompareMem(&(Head->ObservableGuid), &ReferenceGuid, sizeof(ReferenceGuid)) == 0) { + // + // We found the observer that matches ReferenceGuid. Find and delete the subscriber that is + // listening to it. + // + Head->Leaf = _FindAndDeleteSubscriber(Head->Leaf, CallbackInterface); + } else { + // + // Not found. Keep searching. + // + Head->Next = FindAndDeleteSubscriber(Head->Next, ReferenceGuid, CallbackInterface); + } + } + + return Head; +} + +/** Remove all observables. + * + * Remove all observable guids and all interfaces subscribed to them. + * + * @param VOID No parameters. + * + * @return EFI_SUCCESS Successfully removed all observables and subscribed interfaces. + **/ +EFI_STATUS +EFIAPI +RemoveAllObservables( + VOID + ) +{ + mObservableDb = DeleteAllObservables(mObservableDb); + + return EFI_SUCCESS; +} + +/** Subscribe an interface with an observable guid. + * + * Use this to register a callback function with a guid. The function provided by CallbackInterface will be executed + * whenever the appropriate observable instance specified by ReferenceGuid calls Publish. + * + * @param EFI_GUID ReferenceGuid The observable guid that the callback interface will subscribe to. + * OBS_CASLLBACK CallbackInterface A pointer to the function that is subscribing to the observable. + * + * @return EFI_SUCCESS Successfully subscribed the interface to the observable guid. + * EFI_NOT_FOUND No match could be found between the provided guid and existing observables. + * EFI_OUT_OF_RESOURCES Could not subscribe to this observer due to resource limitations. + * EFI_INVALID_PARAMETER Interface is already subscribed to this observer. + **/ +EFI_STATUS +EFIAPI +Subscribe ( + IN EFI_GUID ReferenceGuid, + IN OBS_CALLBACK CallbackInterface + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + OBS_TREE* TempTree = NULL; + OBS_LEAF* Last = NULL; + OBS_LEAF* TempLeaf = NULL; + OBS_LEAF* NewLeaf = NULL; + BOOLEAN Found = FALSE; + + if (mObservableDb != NULL) { + // + // Find the observable guid that we're looking for. + // + for (TempTree = mObservableDb; TempTree != NULL; TempTree = TempTree->Next) { + if (CompareMem(&(TempTree->ObservableGuid), &ReferenceGuid, sizeof(ReferenceGuid)) == 0) { + Found = TRUE; + break; + } + } + if (Found) { + // + // Prepare to add a new leaf. + // + NewLeaf = AllocateZeroPool(sizeof(OBS_LEAF)); + if (!NewLeaf) { + Status = EFI_OUT_OF_RESOURCES; + } else { + NewLeaf->Next = NULL; + NewLeaf->Observer = CallbackInterface; + // + // Go to the end of the list of observers. + // + if (TempTree->Leaf != NULL) { + // + // First check to see if this is a duplicate observer. + // + Found = FALSE; + TempLeaf = TempTree->Leaf; + do { + Last = TempLeaf; + if (TempLeaf->Observer == CallbackInterface) { + // + // It is, so let's abort this process. + // + Found = TRUE; + break; + } + TempLeaf = TempLeaf->Next; + } while (TempLeaf != NULL); + TempLeaf = Last; + + // + // Check for duplicates. + // + if (Found) { + gBS->FreePool(NewLeaf); + Status = EFI_INVALID_PARAMETER; + } else { + // + // At this point, TempLeaf->Next will be the end of the list. + // + TempLeaf->Next = NewLeaf; + } + } else { + // + // There are no observers listening to this guid. Start a new list. + // + TempTree->Leaf = NewLeaf; + } + } + } else { + Status = EFI_NOT_FOUND; + } + } else { + Status = EFI_NOT_FOUND; + } + + return Status; +} + +/** Unsubscribe an interface with an observable guid. + * + * Use this to remove an interface from the callback list associated with an observable guid. + * + * @param EFI_GUID ReferenceGuid The observable guid to unsubscribe the interface from. + * OBS_NOTIFY_INTERFACE NotifyCallback A pointer to the interface that is being unsubscribed. + * + * @return EFI_SUCCESS Successfully unsubscribed the interface from the observable guid. + **/ +EFI_STATUS +EFIAPI +Unsubscribe ( + IN EFI_GUID ReferenceGuid, + IN OBS_CALLBACK CallbackInterface + ) +{ + mObservableDb = FindAndDeleteSubscriber(mObservableDb, ReferenceGuid, CallbackInterface); + + return EFI_SUCCESS; +} + +/** Notify observing functions. + * + * Use this to notify all functions who are subscribed to the guid specified by ReferenceGuid. + * + * @param EFI_GUID ReferenceGuid The observable guid that contains the the list of interfaces to be notified. + * VOID* Data Parameter context to be passed to the notification function. + * + * @return EFI_SUCCESS Successfully notified all observers listening to this guid. + * EFI_NOT_FOUND No match could be found between the provided guid and existing observables. + **/ +EFI_STATUS +EFIAPI +Publish ( + IN EFI_GUID ReferenceGuid, + IN OUT VOID* Data + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + OBS_TREE* TempTree = NULL; + OBS_LEAF* TempLeaf = NULL; + BOOLEAN Found = FALSE; + + if (mObservableDb != NULL) { + // + // Find the observable guid that we're looking for. + // + for (TempTree = mObservableDb; TempTree != NULL; TempTree = TempTree->Next) { + if (CompareMem(&(TempTree->ObservableGuid), &ReferenceGuid, sizeof(ReferenceGuid)) == 0) { + Found = TRUE; + break; + } + } + if (Found) { + // + // Notify every listener by performing each provided callback. + // + for (TempLeaf = TempTree->Leaf; TempLeaf != NULL; TempLeaf = TempLeaf->Next) { + if (TempLeaf->Observer != NULL) { + // + // Execute the callback. + // + TempLeaf->Observer(Data); + } + } + } else { + Status = EFI_NOT_FOUND; + } + } else { + Status = EFI_NOT_FOUND; + } + + return Status; +} + +/** Creates a new observable. + * + * Create a new observable that can be observed with the use of Subscribe function. + * + * @param EFI_GUID ReferenceGuid The observable guid to add. + * + * @return EFI_SUCCESS Successfully added observable. + * EFI_INVALID_PARAMETER Observable already exists. + **/ +EFI_STATUS +EFIAPI +AddObservable ( + IN EFI_GUID ReferenceGuid + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + OBS_TREE* TempTree = NULL; + OBS_TREE* Last = NULL; + OBS_TREE* NewTree = NULL; + BOOLEAN Found = FALSE; + + if (mObservableDb != NULL) { + if (mObservableDb->Next != NULL) { + // + // Iterate to the end of the observable list while checking to see if we aren't creating a duplicate. + // + TempTree = mObservableDb->Next; + do { + Last = TempTree; + if (CompareMem(&(TempTree->ObservableGuid), &ReferenceGuid, sizeof(ReferenceGuid)) == 0) { + Found = TRUE; + break; + } + TempTree = TempTree->Next; + } while (TempTree != NULL); + TempTree = Last; + } else { + TempTree = mObservableDb; + } + if (Found) { + // + // Duplicate, so reject the parameter. + // + Status = EFI_INVALID_PARAMETER; + } else { + // + // TempTree->Next is our target. Prepare to add a new tree link. + // + NewTree = AllocateZeroPool(sizeof(OBS_TREE)); + if (NewTree) { + NewTree->Next = NULL; + NewTree->Leaf = NULL; + CopyMem(&(NewTree->ObservableGuid), &ReferenceGuid, sizeof(ReferenceGuid)); + TempTree->Next = NewTree; + } else { + Status = EFI_OUT_OF_RESOURCES; + } + } + } else { + // + // mObservableDb has not been created yet. Let's do that. + // + NewTree = AllocateZeroPool(sizeof(OBS_TREE)); + if (NewTree) { + NewTree->Next = NULL; + NewTree->Leaf = NULL; + CopyMem(&(NewTree->ObservableGuid), &ReferenceGuid, sizeof(ReferenceGuid)); + mObservableDb = NewTree; + } else { + Status = EFI_OUT_OF_RESOURCES; + } + } + + return Status; +} + +/** Remove an observable. + * + * Remove an observable so that it can no longer be subscribed to. In addition, unsubscribe any functions + * that are subscribed to this guid. + * + * @param EFI_GUID ReferenceGuid The observable guid to remove. + * + * @return EFI_SUCCESS Successfully removed observable. + **/ +EFI_STATUS +EFIAPI +RemoveObservable ( + IN EFI_GUID ReferenceGuid + ) +{ + mObservableDb = FindAndDeleteObservable(mObservableDb, ReferenceGuid); + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/PlatformDxe/Observable/Observable.h b/Vlv2TbltDevicePkg/PlatformDxe/Observable/Observable.h new file mode 100644 index 0000000000..a6bc62bb0b --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/Observable/Observable.h @@ -0,0 +1,142 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + Observable.h + +Abstract: + + Prototypes for Observable protocol implementation +--*/ + +#ifndef _OBSERVABLE_H_ +#define _OBSERVABLE_H_ +#include "PlatformDxe.h" +#include "Protocol/Observable.h" + +// +// Prototypes +// + +/** Install observable protocol. + * + * Install interface and initialize the observable protocol. + * + * @param VOID No parameters. + * + * @return EFI_SUCCESS Successfully installed and initialized the protocol. + **/ +EFI_STATUS +InitializeObservableProtocol( + VOID + ); + +/** Remove all observables. + * + * Remove all observable guids and all interfaces subscribed to them. + * + * @param VOID No parameters. + * + * @return EFI_SUCCESS Successfully removed all observables and subscribed interfaces. + **/ +EFI_STATUS +EFIAPI +RemoveAllObservables( + VOID + ); + +/** Subscribe an interface with an observable guid. + * + * Use this to register a callback function with a guid. The function provided by CallbackInterface will be executed + * whenever the appropriate observable instance specified by ReferenceGuid calls Publish. + * + * @param EFI_GUID ReferenceGuid The observable guid that the callback interface will subscribe to. + * OBS_CALLBACK CallbackInterface A pointer to the function that is subscribing to the observable. + * + * @return EFI_SUCCESS Successfully subscribed the interface to the observable guid. + * EFI_NOT_FOUND No match could be found between the provided guid and existing observables. + * EFI_OUT_OF_RESOURCES Could not subscribe to this observer due to resource limitations. + * EFI_INVALID_PARAMETER Interface is already subscribed to this observer. + **/ +EFI_STATUS +EFIAPI +Subscribe ( + IN EFI_GUID ReferenceGuid, + IN OBS_CALLBACK CallbackInterface + ); + +/** Unsubscribe an interface with an observable guid. + * + * Use this to remove an interface from the callback list associated with an observable guid. + * + * @param EFI_GUID ReferenceGuid The observable guid to unsubscribe the interface from. + * OBS_CALLBACK CallbackInterface A pointer to the interface that is being unsubscribed. + * + * @return EFI_SUCCESS Successfully unsubscribed the interface from the observable guid. + **/ +EFI_STATUS +EFIAPI +Unsubscribe ( + IN EFI_GUID ReferenceGuid, + IN OBS_CALLBACK CallbackInterface + ); + +/** Notify observing functions. + * + * Use this to notify all functions who are subscribed to the guid specified by ReferenceGuid. + * + * @param EFI_GUID ReferenceGuid The observable guid that contains the list of interfaces to be notified. + * VOID* Data Parameter context to be passed to the subscribed function. + * + * @return EFI_SUCCESS Successfully notified all observers listening to this guid. + * EFI_NOT_FOUND No match could be found between the provided guid and existing observables. + **/ +EFI_STATUS +EFIAPI +Publish ( + IN EFI_GUID ReferenceGuid, + IN OUT VOID* Data + ); + +/** Creates a new observable. + * + * Create a new observable that can be observed with the use of Subscribe function. + * + * @param EFI_GUID ReferenceGuid The observable guid to add. + * + * @return EFI_SUCCESS Successfully added observable. + * EFI_INVALID_PARAMETER Observable already exists. + **/ +EFI_STATUS +EFIAPI +AddObservable ( + IN EFI_GUID ReferenceGuid + ); + +/** Remove an observable. + * + * Remove an observable so that it can no longer be subscribed to. In addition, unsubscribe any functions + * that are subscribed to this guid. + * + * @param EFI_GUID ReferenceGuid The observable guid to remove. + * + * @return EFI_SUCCESS Successfully removed observable. + **/ +EFI_STATUS +EFIAPI +RemoveObservable ( + IN EFI_GUID ReferenceGuid + ); + +#endif diff --git a/Vlv2TbltDevicePkg/PlatformDxe/PciBus.h b/Vlv2TbltDevicePkg/PlatformDxe/PciBus.h new file mode 100644 index 0000000000..89e31d265a --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/PciBus.h @@ -0,0 +1,384 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + + +#ifndef _EFI_PCI_BUS_H_ +#define _EFI_PCI_BUS_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +typedef struct _PCI_IO_DEVICE PCI_IO_DEVICE; +typedef struct _PCI_BAR PCI_BAR; + +#define EFI_PCI_RID(Bus, Device, Function) (((UINT32)Bus << 8) + ((UINT32)Device << 3) + (UINT32)Function) +#define EFI_PCI_BUS_OF_RID(RID) ((UINT32)RID >> 8) + +#define EFI_PCI_IOV_POLICY_ARI 0x0001 +#define EFI_PCI_IOV_POLICY_SRIOV 0x0002 +#define EFI_PCI_IOV_POLICY_MRIOV 0x0004 + +typedef enum { + PciBarTypeUnknown = 0, + PciBarTypeIo16, + PciBarTypeIo32, + PciBarTypeMem32, + PciBarTypePMem32, + PciBarTypeMem64, + PciBarTypePMem64, + PciBarTypeIo, + PciBarTypeMem, + PciBarTypeMaxType +} PCI_BAR_TYPE; + + +#define VGABASE1 0x3B0 +#define VGALIMIT1 0x3BB + +#define VGABASE2 0x3C0 +#define VGALIMIT2 0x3DF + +#define ISABASE 0x100 +#define ISALIMIT 0x3FF + +// +// PCI BAR parameters +// +struct _PCI_BAR { + UINT64 BaseAddress; + UINT64 Length; + UINT64 Alignment; + PCI_BAR_TYPE BarType; + BOOLEAN Prefetchable; + UINT8 MemType; + UINT16 Offset; +}; + +// +// defined in PCI Card Specification, 8.0 +// +#define PCI_CARD_MEMORY_BASE_0 0x1C +#define PCI_CARD_MEMORY_LIMIT_0 0x20 +#define PCI_CARD_MEMORY_BASE_1 0x24 +#define PCI_CARD_MEMORY_LIMIT_1 0x28 +#define PCI_CARD_IO_BASE_0_LOWER 0x2C +#define PCI_CARD_IO_BASE_0_UPPER 0x2E +#define PCI_CARD_IO_LIMIT_0_LOWER 0x30 +#define PCI_CARD_IO_LIMIT_0_UPPER 0x32 +#define PCI_CARD_IO_BASE_1_LOWER 0x34 +#define PCI_CARD_IO_BASE_1_UPPER 0x36 +#define PCI_CARD_IO_LIMIT_1_LOWER 0x38 +#define PCI_CARD_IO_LIMIT_1_UPPER 0x3A +#define PCI_CARD_BRIDGE_CONTROL 0x3E + +#define PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE BIT8 +#define PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE BIT9 + +#define PPB_BAR_0 0 +#define PPB_BAR_1 1 +#define PPB_IO_RANGE 2 +#define PPB_MEM32_RANGE 3 +#define PPB_PMEM32_RANGE 4 +#define PPB_PMEM64_RANGE 5 +#define PPB_MEM64_RANGE 0xFF + +#define P2C_BAR_0 0 +#define P2C_MEM_1 1 +#define P2C_MEM_2 2 +#define P2C_IO_1 3 +#define P2C_IO_2 4 + +#define EFI_BRIDGE_IO32_DECODE_SUPPORTED 0x0001 +#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED 0x0002 +#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED 0x0004 +#define EFI_BRIDGE_IO16_DECODE_SUPPORTED 0x0008 +#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED 0x0010 +#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED 0x0020 +#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED 0x0040 + +#define PCI_MAX_HOST_BRIDGE_NUM 0x0010 + +// +// Define option for attribute +// +#define EFI_SET_SUPPORTS 0 +#define EFI_SET_ATTRIBUTES 1 + +#define PCI_IO_DEVICE_SIGNATURE SIGNATURE_32 ('p', 'c', 'i', 'o') + +struct _PCI_IO_DEVICE { + UINT32 Signature; + EFI_HANDLE Handle; + EFI_PCI_IO_PROTOCOL PciIo; + LIST_ENTRY Link; + + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL PciDriverOverride; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + EFI_LOAD_FILE2_PROTOCOL LoadFile2; + + // + // PCI configuration space header type + // + PCI_TYPE00 Pci; + + // + // Bus number, Device number, Function number + // + UINT8 BusNumber; + UINT8 DeviceNumber; + UINT8 FunctionNumber; + + // + // BAR for this PCI Device + // + PCI_BAR PciBar[PCI_MAX_BAR]; + + // + // The bridge device this pci device is subject to + // + PCI_IO_DEVICE *Parent; + + // + // A linked list for children Pci Device if it is bridge device + // + LIST_ENTRY ChildList; + + // + // TURE if the PCI bus driver creates the handle for this PCI device + // + BOOLEAN Registered; + + // + // TRUE if the PCI bus driver successfully allocates the resource required by + // this PCI device + // + BOOLEAN Allocated; + + // + // The attribute this PCI device currently set + // + UINT64 Attributes; + + // + // The attributes this PCI device actually supports + // + UINT64 Supports; + + // + // The resource decode the bridge supports + // + UINT32 Decodes; + + // + // TRUE if the ROM image is from the PCI Option ROM BAR + // + BOOLEAN EmbeddedRom; + + // + // The OptionRom Size + // + UINT64 RomSize; + + // + // The OptionRom Size + // + UINT64 RomBase; + + // + // TRUE if all OpROM (in device or in platform specific position) have been processed + // + BOOLEAN AllOpRomProcessed; + + // + // TRUE if there is any EFI driver in the OptionRom + // + BOOLEAN BusOverride; + + // + // A list tracking reserved resource on a bridge device + // + LIST_ENTRY ReservedResourceList; + + // + // A list tracking image handle of platform specific overriding driver + // + LIST_ENTRY OptionRomDriverList; + + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ResourcePaddingDescriptors; + EFI_HPC_PADDING_ATTRIBUTES PaddingAttributes; + + BOOLEAN IsPciExp; + + // + // For SR-IOV + // + UINT8 PciExpressCapabilityOffset; + UINT32 AriCapabilityOffset; + UINT32 SrIovCapabilityOffset; + UINT32 MrIovCapabilityOffset; + PCI_BAR VfPciBar[PCI_MAX_BAR]; + UINT32 SystemPageSize; + UINT16 InitialVFs; + UINT16 ReservedBusNum; + + // + // Per PCI to PCI Bridge spec, I/O window is 4K aligned, + // but some chipsets support non-stardard I/O window aligments less than 4K. + // This field is used to support this case. + // + UINT16 BridgeIoAlignment; +}; + +#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ + CR (a, PCI_IO_DEVICE, PciIo, PCI_IO_DEVICE_SIGNATURE) + +#define PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS(a) \ + CR (a, PCI_IO_DEVICE, PciDriverOverride, PCI_IO_DEVICE_SIGNATURE) + +#define PCI_IO_DEVICE_FROM_LINK(a) \ + CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE) + +#define PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS(a) \ + CR (a, PCI_IO_DEVICE, LoadFile2, PCI_IO_DEVICE_SIGNATURE) + + + +// +// Global Variables +// +extern EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *gEfiIncompatiblePciDeviceSupport; +extern EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2; +extern BOOLEAN gFullEnumeration; +extern UINTN gPciHostBridgeNumber; +extern EFI_HANDLE gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM]; +extern UINT64 gAllOne; +extern UINT64 gAllZero; +extern EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol; +extern EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol; +extern BOOLEAN mReserveIsaAliases; +extern BOOLEAN mReserveVgaAliases; + +/** + Macro that checks whether device is a GFX device. + + @param _p Specified device. + + @retval TRUE Device is a a GFX device. + @retval FALSE Device is not a a GFX device. + +**/ +#define IS_PCI_GFX(_p) IS_CLASS2 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_OTHER) + +/** + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supported. + + @param This Protocol instance pointer. + @param Controller Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child. + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_ALREADY_STARTED This driver is already running on this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +PciBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Start this driver on ControllerHandle and enumerate Pci bus and start + all device under PCI bus. + + @param This Protocol instance pointer. + @param Controller Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child. + device to start. + + @retval EFI_SUCCESS This driver is added to ControllerHandle. + @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +PciBusDriverBindingStart ( + 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 Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle. + @retval other This driver was not removed from this device. + +**/ +EFI_STATUS +EFIAPI +PciBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +#endif diff --git a/Vlv2TbltDevicePkg/PlatformDxe/PciDevice.c b/Vlv2TbltDevicePkg/PlatformDxe/PciDevice.c new file mode 100644 index 0000000000..16aaa18563 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/PciDevice.c @@ -0,0 +1,517 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + PciDevice.c + +Abstract: + + Platform Initialization Driver. + +Revision History + +--*/ + +#include "PlatformDxe.h" +#include "Library/DxeServicesTableLib.h" +#include "PciBus.h" +#include "Guid/PciLanInfo.h" + +extern VOID *mPciLanInfo; +extern UINTN mPciLanCount; + +extern EFI_HANDLE mImageHandle; +extern SYSTEM_CONFIGURATION mSystemConfiguration; + + +VOID *mPciRegistration; +#define NCR_VENDOR_ID 0x1000 +#define ATI_VENDOR_ID 0x1002 +#define INTEL_VENDOR_ID 0x8086 +#define ATI_RV423_ID 0x5548 +#define ATI_RV423_ID2 0x5d57 +#define ATI_RV380_ID 0x3e50 +#define ATI_RV370_ID 0x5b60 +#define SI_VENDOR_ID 0x1095 +#define SI_SISATA_ID 0x3114 +#define SI_SIRAID_PCIUNL 0x40 +#define INTEL_82573E_IDER 0x108D + +typedef struct { + UINT8 ClassCode; + UINT8 SubClassCode; + UINT16 VendorId; + UINT16 DeviceId; +} BAD_DEVICE_TABLE; + +BAD_DEVICE_TABLE BadDeviceTable[] = { + {(UINT8)PCI_CLASS_MASS_STORAGE,(UINT8)PCI_CLASS_MASS_STORAGE_SCSI,(UINT16)NCR_VENDOR_ID, (UINT16)0xffff}, // Any NCR cards + {(UINT8)PCI_CLASS_MASS_STORAGE,(UINT8)PCI_CLASS_MASS_STORAGE_IDE,(UINT16)INTEL_VENDOR_ID, (UINT16)INTEL_82573E_IDER}, // Intel i82573E Tekoa GBit Lan IDE-R + {(UINT8)0xff,(UINT8)0xff,(UINT16)0xffff,(UINT16)0xffff} + }; + +EFI_STATUS +PciBusDriverHook ( + ) +{ + EFI_STATUS Status; + EFI_EVENT FilterEvent; + + // + // Register for callback to PCI I/O protocol + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + PciBusEvent, + NULL, + &FilterEvent + ); + ASSERT_EFI_ERROR(Status); + + // + // Register for protocol notifications on this event + // + Status = gBS->RegisterProtocolNotify ( + &gEfiPciIoProtocolGuid, + FilterEvent, + &mPciRegistration + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +VOID +InitBadBars( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 VendorId, + IN UINT16 DeviceId + ) +{ + + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + UINT64 BaseAddress = 0; + UINT64 TempBaseAddress = 0; + UINT8 RevId = 0; + UINT32 Bar; + UINT64 IoSize; + UINT64 MemSize; + UINTN MemSizeBits; + + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo); + switch ( VendorId) { + case ATI_VENDOR_ID: + // + // ATI fix-ups. At this time all ATI cards in BadDeviceTable + // have same problem in that OPROM BAR needs to be increased. + // + Bar = 0x30 ; + // + // Get original BAR address + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + Bar, + 1, + (VOID *) &BaseAddress + ); + // + // Find BAR size + // + TempBaseAddress = 0xffffffff; + Status = PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + Bar, + 1, + (VOID *) &TempBaseAddress + ); + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + Bar, + 1, + (VOID *) &TempBaseAddress + ); + TempBaseAddress &= 0xfffffffe; + MemSize = 1; + while ((TempBaseAddress & 0x01) == 0) { + TempBaseAddress = TempBaseAddress >> 1; + MemSize = MemSize << 1; + } + + // + // Free up allocated memory memory and re-allocate with increased size. + // + Status = gDS->FreeMemorySpace ( + BaseAddress, + MemSize + ); + // + // Force new alignment + // + MemSize = 0x8000000; + MemSizeBits = 28; + + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateAnySearchBottomUp, + EfiGcdMemoryTypeMemoryMappedIo, + MemSizeBits, // Alignment + MemSize, + &BaseAddress, + mImageHandle, + NULL + ); + Status = PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + Bar, + 1, + (VOID *) &BaseAddress + ); + + break; + case NCR_VENDOR_ID: +#define MIN_NCR_IO_SIZE 0x800 +#define NCR_GRAN 11 // 2**11 = 0x800 + // + // NCR SCSI cards like 8250S lie about IO needed. Assign as least 0x80. + // + for (Bar = 0x10; Bar < 0x28; Bar+= 4) { + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + Bar, + 1, + (VOID *) &BaseAddress + ); + if (BaseAddress && 0x01) { + TempBaseAddress = 0xffffffff; + Status = PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + Bar, + 1, + (VOID *) &TempBaseAddress + ); + TempBaseAddress &= 0xfffffffc; + IoSize = 1; + while ((TempBaseAddress & 0x01) == 0) { + TempBaseAddress = TempBaseAddress >> 1; + IoSize = IoSize << 1; + } + if (IoSize < MIN_NCR_IO_SIZE) { + Status = gDS->FreeIoSpace ( + BaseAddress, + IoSize + ); + + Status = gDS->AllocateIoSpace ( + EfiGcdAllocateAnySearchTopDown, + EfiGcdIoTypeIo, + NCR_GRAN, // Alignment + MIN_NCR_IO_SIZE, + &BaseAddress, + mImageHandle, + NULL + ); + TempBaseAddress = BaseAddress + 1; + Status = PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + Bar, + 1, + (VOID *) &TempBaseAddress + ); + } + } + } + + break; + + case INTEL_VENDOR_ID: + if (DeviceId == INTEL_82573E_IDER) { + // + // Tekoa i82573E IDE-R fix-ups. At this time A2 step and earlier parts do not + // support any BARs except BAR0. Other BARS will actualy map to BAR0 so disable + // them all for Control Blocks and Bus mastering ops as well as Secondary IDE + // Controller. + // All Tekoa A2 or earlier step chips for now. + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_REVISION_ID_OFFSET, + 1, + &RevId + ); + if (RevId <= 0x02) { + for (Bar = 0x14; Bar < 0x24; Bar+= 4) { + // + // Maybe want to clean this up a bit later but for now just clear out the secondary + // Bars don't worry aboyut freeing up thge allocs. + // + TempBaseAddress = 0x0; + Status = PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + Bar, + 1, + (VOID *) &TempBaseAddress + ); + } // end for + } + else + { + // + //Tekoa A3 or above: + //Clear bus master base address (PCI register 0x20) + //since Tekoa does not fully support IDE Bus Mastering + // + TempBaseAddress = 0x0; + Status = PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + 0x20, + 1, + (VOID *) &TempBaseAddress + ); + } + } + break; + + default: + break; + } + return; +} + +VOID +ProgramPciLatency( + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + EFI_STATUS Status; + + // + // Program Master Latency Timer + // + if (mSystemConfiguration.PciLatency != 0) { + Status = PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint8, + PCI_LATENCY_TIMER_OFFSET, + 1, + &mSystemConfiguration.PciLatency + ); + } + return; +} + +/** +During S5 shutdown, we need to program PME in all LAN devices. +Here we identify LAN devices and save their bus/dev/func. + +**/ +VOID +SavePciLanAddress( + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + EFI_STATUS Status; + UINTN PciSegment, + PciBus, + PciDevice, + PciFunction; + VOID *NewBuffer; + PCI_LAN_INFO *x; + + Status = PciIo->GetLocation ( + PciIo, + &PciSegment, + &PciBus, + &PciDevice, + &PciFunction + ); + if (EFI_ERROR (Status)) { + return; + } + + mPciLanCount ++; + Status = gBS->AllocatePool ( + EfiBootServicesData, + mPciLanCount * sizeof(PCI_LAN_INFO), + &NewBuffer + ); + if (EFI_ERROR (Status)) { + return; + } + + if (mPciLanCount > 1) { + // + // copy old data into new, larger buffer + // + gBS->CopyMem ( + NewBuffer, + mPciLanInfo, + (mPciLanCount - 1) * sizeof(PCI_LAN_INFO) + ); + + // + // free the old memory buffer + // + gBS->FreePool (mPciLanInfo); + + } + + // + // init the new entry + // + x = (PCI_LAN_INFO *)NewBuffer + (mPciLanCount - 1); + x->PciBus = (UINT8)PciBus; + x->PciDevice = (UINT8)PciDevice; + x->PciFunction = (UINT8)PciFunction; + + mPciLanInfo = NewBuffer; + + return; +} + +/** + @param Event the event that is signaled. + @param Context not used here. + + +**/ +VOID +EFIAPI +PciBusEvent ( + IN EFI_EVENT Event, + IN VOID* Context + ) +{ + + EFI_STATUS Status; + UINTN BufferSize; + EFI_HANDLE Handle; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_IO_DEVICE *PciIoDevice; + UINT64 Supports; + UINTN Index; + UINT8 mCacheLineSize = 0x10; + + while (TRUE) { + BufferSize = sizeof (EFI_HANDLE); + Status = gBS->LocateHandle ( + ByRegisterNotify, + NULL, + mPciRegistration, + &BufferSize, + &Handle + ); + if (EFI_ERROR (Status)) { + // + // If no more notification events exist + // + return; + } + + Status = gBS->HandleProtocol ( + Handle, + &gEfiPciIoProtocolGuid, + (void **)&PciIo + ); + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo); + + // + // Enable I/O for bridge so port 0x80 codes will come out + // + if (PciIoDevice->Pci.Hdr.VendorId == V_PCH_INTEL_VENDOR_ID) + { + Status = PciIo->Attributes( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + Supports &= EFI_PCI_DEVICE_ENABLE; + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + break; + } + + // + // Program PCI Latency Timer + // + ProgramPciLatency(PciIo); + + // + // Program Cache Line Size to 64 bytes (0x10 DWORDs) + // + Status = PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint8, + PCI_CACHELINE_SIZE_OFFSET, + 1, + &mCacheLineSize + ); + + // + // If PCI LAN device, save bus/dev/func info + // so we can program PME during S5 shutdown + // + if (PciIoDevice->Pci.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) { + SavePciLanAddress(PciIo); + break; + } + + // + // Workaround for cards with bad BARs + // + Index = 0; + while (BadDeviceTable[Index].ClassCode != 0xff) { + if (BadDeviceTable[Index].DeviceId == 0xffff) { + if ((PciIoDevice->Pci.Hdr.ClassCode[2] == BadDeviceTable[Index].ClassCode) && + (PciIoDevice->Pci.Hdr.ClassCode[1] == BadDeviceTable[Index].SubClassCode) && + (PciIoDevice->Pci.Hdr.VendorId == BadDeviceTable[Index].VendorId)) { + InitBadBars(PciIo,BadDeviceTable[Index].VendorId,BadDeviceTable[Index].DeviceId); + } + } else { + if ((PciIoDevice->Pci.Hdr.ClassCode[2] == BadDeviceTable[Index].ClassCode) && + (PciIoDevice->Pci.Hdr.ClassCode[1] == BadDeviceTable[Index].SubClassCode) && + (PciIoDevice->Pci.Hdr.VendorId == BadDeviceTable[Index].VendorId) && + (PciIoDevice->Pci.Hdr.DeviceId == BadDeviceTable[Index].DeviceId)) { + + InitBadBars(PciIo,BadDeviceTable[Index].VendorId,BadDeviceTable[Index].DeviceId); + } + } + ++Index; + } + break; + } + + return; +} + diff --git a/Vlv2TbltDevicePkg/PlatformDxe/Platform.c b/Vlv2TbltDevicePkg/PlatformDxe/Platform.c new file mode 100644 index 0000000000..0f3a414c5b --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/Platform.c @@ -0,0 +1,1661 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + Platform.c + +Abstract: + + Platform Initialization Driver. + + +--*/ + +#include "PlatformDxe.h" +#include "Platform.h" +#include "PchCommonDefinitions.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// VLV2 GPIO GROUP OFFSET +// +#define GPIO_SCORE_OFFSET 0x0000 +#define GPIO_NCORE_OFFSET 0x1000 +#define GPIO_SSUS_OFFSET 0x2000 + +typedef struct { + UINT32 offset; + UINT32 val; +} CFIO_PNP_INIT; + +GPIO_CONF_PAD_INIT mTB_BL_GpioInitData_SC_TRI_Exit_boot_Service[] = +{ +// Pad Name GPIO Number Used As GPO Default Function# INT Capable Interrupt Type PULL H/L MMIO Offset + GPIO_INIT_ITEM("LPC_CLKOUT0 GPIOC_47 " ,TRISTS ,NA ,F0 , , ,NONE ,0x47), + GPIO_INIT_ITEM("LPC_CLKOUT1 GPIOC_48 " ,TRISTS ,NA ,F0 , , ,NONE ,0x41), +}; + + +EFI_GUID mSystemHiiExportDatabase = EFI_HII_EXPORT_DATABASE_GUID; +EFI_GUID mPlatformDriverGuid = EFI_PLATFORM_DRIVER_GUID; +SYSTEM_CONFIGURATION mSystemConfiguration; +SYSTEM_PASSWORDS mSystemPassword; +EFI_HANDLE mImageHandle; +BOOLEAN mMfgMode = FALSE; +VOID *mDxePlatformStringPack; +UINT32 mPlatformBootMode = PLATFORM_NORMAL_MODE; +extern CHAR16 gItkDataVarName[]; + + +EFI_PLATFORM_INFO_HOB mPlatformInfo; +EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *mPciRootBridgeIo; +EFI_EVENT mReadyToBootEvent; + +UINT8 mSmbusRsvdAddresses[] = PLATFORM_SMBUS_RSVD_ADDRESSES; +UINT8 mNumberSmbusAddress = sizeof( mSmbusRsvdAddresses ) / sizeof( mSmbusRsvdAddresses[0] ); +UINT32 mSubsystemVidDid; +UINT32 mSubsystemAudioVidDid; + +UINTN mPciLanCount = 0; +VOID *mPciLanInfo = NULL; +UINTN SpiBase; + +static EFI_SPEAKER_IF_PROTOCOL mSpeakerInterface = { + ProgramToneFrequency, + GenerateBeepTone +}; + +EFI_USB_POLICY_PROTOCOL mUsbPolicyData = {0}; + + +CFIO_PNP_INIT mTB_BL_GpioInitData_SC_TRI_S0ix_Exit_boot_Service[] = +{ + {0x410 ,0x20038e10}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_clkout1_pconf0 + {0x470 ,0x20038e10}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_clkout0_pconf0 + {0x560 ,0x20038e10}, //vlv.gpio.gpscore.cfio_regs_pad_ilb_serirq_pconf0 + {0x450 ,0x20038e10}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_frameb_pconf0 + {0x480 ,0x20038e10}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_clkrunb_pconf0 + {0x420 ,0x20038e10}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_ad3_pconf0 + {0x430 ,0x20038e10}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_ad2_pconf0 + {0x440 ,0x20038e10}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_ad1_pconf0 + {0x460 ,0x20038e10}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_ad0_pconf0 + {0x418 ,0x00000006}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_clkout1_pad_val + {0x478 ,0x00000006}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_clkout0_pad_val + {0x568 ,0x00000006}, //vlv.gpio.gpscore.cfio_regs_pad_ilb_serirq_pad_val + {0x458 ,0x00000006}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_frameb_pad_val + {0x488 ,0x00000006}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_clkrunb_pad_val + {0x428 ,0x00000006}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_ad3_pad_val + {0x438 ,0x00000006}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_ad2_pad_val + {0x448 ,0x00000006}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_ad1_pad_val + {0x468 ,0x00000006}, //vlv.gpio.gpscore.cfio_regs_pad_lpc_ad0_pad_val +}; + +VOID +EfiOrMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ); + +#if defined(FIRMWARE_ID_BACKWARD_COMPATIBLE) && (FIRMWARE_ID_BACKWARD_COMPATIBLE != 0) +STATIC +VOID +InitFirmwareId(); +#endif + + +VOID +InitializeClockRouting( + ); + +VOID +InitializeSlotInfo ( + ); + +#if defined(SENSOR_INFO_VAR_SUPPORT) && SENSOR_INFO_VAR_SUPPORT != 0 +VOID +InitializeSensorInfoVariable ( + ); +#endif + +VOID +InitTcoReset ( + ); + +VOID +InitExI (); + +VOID +InitItk(); + +VOID +InitPlatformBootMode(); + +VOID +InitMfgAndConfigModeStateVar(); + +VOID +InitPchPlatformPolicy ( + IN EFI_PLATFORM_INFO_HOB *PlatformInfo + ); + +VOID +InitVlvPlatformPolicy ( + ); + +VOID +InitSioPlatformPolicy( + ); + +VOID +PchInitBeforeBoot( + ); + +VOID +UpdateDVMTSetup( + ); + +VOID +InitPlatformUsbPolicy ( + VOID + ); + +VOID +InitRC6Policy( + VOID + ); + + +VOID +TristateLpcGpioConfig ( + IN UINT32 Gpio_Mmio_Offset, + IN UINT32 Gpio_Pin_Num, + GPIO_CONF_PAD_INIT* Gpio_Conf_Data + ) + +{ + UINT32 index; + UINT32 mmio_conf0; + UINT32 mmio_padval; + PAD_CONF0 conf0_val; + PAD_VAL pad_val; + + // + // GPIO WELL -- Memory base registers + // + + // + // A0 BIOS Spec doesn't mention it although X0 does. comment out now. + // GPIO write 0x01001002 to IOBASE + Gpio_Mmio_Offset + 0x0900 + // + + for(index=0; index < Gpio_Pin_Num; index++) + { + // + // Calculate the MMIO Address for specific GPIO pin CONF0 register pointed by index. + // + mmio_conf0 = IO_BASE_ADDRESS + Gpio_Mmio_Offset + R_PCH_CFIO_PAD_CONF0 + Gpio_Conf_Data[index].offset * 16; + mmio_padval= IO_BASE_ADDRESS + Gpio_Mmio_Offset + R_PCH_CFIO_PAD_VAL + Gpio_Conf_Data[index].offset * 16; + +#ifdef EFI_DEBUG + DEBUG ((EFI_D_INFO, "%s, ", Gpio_Conf_Data[index].pad_name)); + +#endif + DEBUG ((EFI_D_INFO, "Usage = %d, Func# = %d, IntType = %d, Pull Up/Down = %d, MMIO Base = 0x%08x, ", + Gpio_Conf_Data[index].usage, + Gpio_Conf_Data[index].func, + Gpio_Conf_Data[index].int_type, + Gpio_Conf_Data[index].pull, + mmio_conf0)); + + // + // Step 1: PadVal Programming + // + pad_val.dw = MmioRead32(mmio_padval); + + // + // Config PAD_VAL only for GPIO (Non-Native) Pin + // + if(Native != Gpio_Conf_Data[index].usage) + { + pad_val.dw &= ~0x6; // Clear bits 1:2 + pad_val.dw |= (Gpio_Conf_Data[index].usage & 0x6); // Set bits 1:2 according to PadVal + + // + // set GPO default value + // + if(Gpio_Conf_Data[index].usage == GPO && Gpio_Conf_Data[index].gpod4 != NA) + { + pad_val.r.pad_val = Gpio_Conf_Data[index].gpod4; + } + } + + + DEBUG ((EFI_D_INFO, "Set PAD_VAL = 0x%08x, ", pad_val.dw)); + + MmioWrite32(mmio_padval, pad_val.dw); + + // + // Step 2: CONF0 Programming + // Read GPIO default CONF0 value, which is assumed to be default value after reset. + // + conf0_val.dw = MmioRead32(mmio_conf0); + + // + // Set Function # + // + conf0_val.r.Func_Pin_Mux = Gpio_Conf_Data[index].func; + + if(GPO == Gpio_Conf_Data[index].usage) + { + // + // If used as GPO, then internal pull need to be disabled + // + conf0_val.r.Pull_assign = 0; // Non-pull + } + else + { + // + // Set PullUp / PullDown + // + if(P_20K_H == Gpio_Conf_Data[index].pull) + { + conf0_val.r.Pull_assign = 0x1; // PullUp + conf0_val.r.Pull_strength = 0x2;// 20K + } + else if(P_20K_L == Gpio_Conf_Data[index].pull) + { + conf0_val.r.Pull_assign = 0x2; // PullDown + conf0_val.r.Pull_strength = 0x2;// 20K + } + else if(P_NONE == Gpio_Conf_Data[index].pull) + { + conf0_val.r.Pull_assign = 0; // Non-pull + } + else + { + ASSERT(FALSE); // Invalid value + } + } + + // + // Set INT Trigger Type + // + conf0_val.dw &= ~0x0f000000; // Clear bits 27:24 + + // + // Set INT Trigger Type + // + if(TRIG_ == Gpio_Conf_Data[index].int_type) + { + // + // Interrupt not capable, clear bits 27:24 + // + } + else + { + conf0_val.dw |= (Gpio_Conf_Data[index].int_type & 0x0f)<<24; + } + + DEBUG ((EFI_D_INFO, "Set CONF0 = 0x%08x\n", conf0_val.dw)); + + // + // Write back the targeted GPIO config value according to platform (board) GPIO setting + // + MmioWrite32 (mmio_conf0, conf0_val.dw); + } + + // A0 BIOS Spec doesn't mention it although X0 does. comment out now. + // GPIO SCORE write 0x01001002 to IOBASE + 0x0900 + // +} + +VOID +EFIAPI +SpiBiosProtectionFunction( + EFI_EVENT Event, + VOID *Context + ) +{ + + UINTN mPciD31F0RegBase; + UINTN BiosFlaLower = 0; + UINTN BiosFlaLimit = 0x7fffff; + + BiosFlaLower = PcdGet32(PcdFlashMicroCodeAddress)-PcdGet32(PcdFlashAreaBaseAddress); + + + mPciD31F0RegBase = MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + SpiBase = MmioRead32(mPciD31F0RegBase + R_PCH_LPC_SPI_BASE) & B_PCH_LPC_SPI_BASE_BAR; + + // + //Set SMM_BWP, WPD and LE bit + // + MmioOr32 ((UINTN) (SpiBase + R_PCH_SPI_BCR), (UINT8) B_PCH_SPI_BCR_SMM_BWP); + MmioAnd32 ((UINTN) (SpiBase + R_PCH_SPI_BCR), (UINT8)(~B_PCH_SPI_BCR_BIOSWE)); + MmioOr32 ((UINTN) (SpiBase + R_PCH_SPI_BCR), (UINT8) B_PCH_SPI_BCR_BLE); + + // + //First check if FLOCKDN or PR0FLOCKDN is set. No action if either of them set already. + // + if( (MmioRead16(SpiBase + R_PCH_SPI_HSFS) & B_PCH_SPI_HSFS_FLOCKDN) != 0 || + (MmioRead32(SpiBase + R_PCH_SPI_IND_LOCK)& B_PCH_SPI_IND_LOCK_PR0) != 0) { + // + //Already locked. we could take no action here + // + DEBUG((EFI_D_INFO, "PR0 already locked down. Stop configuring PR0.\n")); + return; + } + + // + //Set PR0 + // + MmioOr32((UINTN)(SpiBase + R_PCH_SPI_PR0), + B_PCH_SPI_PR0_RPE|B_PCH_SPI_PR0_WPE|\ + (B_PCH_SPI_PR0_PRB_MASK&(BiosFlaLower>>12))|(B_PCH_SPI_PR0_PRL_MASK&(BiosFlaLimit>>12)<<16)); + + // + //Lock down PR0 + // + MmioOr16 ((UINTN) (SpiBase + R_PCH_SPI_HSFS), (UINT16) (B_PCH_SPI_HSFS_FLOCKDN)); + + // + // Verify if it's really locked. + // + if ((MmioRead16 (SpiBase + R_PCH_SPI_HSFS) & B_PCH_SPI_HSFS_FLOCKDN) == 0) { + DEBUG((EFI_D_ERROR, "Failed to lock down PR0.\n")); + } + + return; + +} + +VOID +EFIAPI +InitPciDevPME ( + EFI_EVENT Event, + VOID *Context + ) +{ + UINTN VarSize; + EFI_STATUS Status; + + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + NORMAL_SETUP_NAME, + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &mSystemConfiguration + ); + + // + //Program HDA PME_EN + // + PchAzaliaPciCfg32Or (R_PCH_HDA_PCS, B_PCH_HDA_PCS_PMEE); + + // + //Program SATA PME_EN + // + PchSataPciCfg32Or (R_PCH_SATA_PMCS, B_PCH_SATA_PMCS_PMEE); + + DEBUG ((EFI_D_INFO, "InitPciDevPME mSystemConfiguration.EhciPllCfgEnable = 0x%x \n",mSystemConfiguration.EhciPllCfgEnable)); + if (mSystemConfiguration.EhciPllCfgEnable != 1) { + // + //Program EHCI PME_EN + // + PchMmPci32Or ( + 0, + 0, + PCI_DEVICE_NUMBER_PCH_USB, + PCI_FUNCTION_NUMBER_PCH_EHCI, + R_PCH_EHCI_PWR_CNTL_STS, + B_PCH_EHCI_PWR_CNTL_STS_PME_EN + ); + } + { + UINTN EhciPciMmBase; + UINT32 Buffer32 = 0; + + EhciPciMmBase = MmPciAddress (0, + 0, + PCI_DEVICE_NUMBER_PCH_USB, + PCI_FUNCTION_NUMBER_PCH_EHCI, + 0 + ); + DEBUG ((EFI_D_INFO, "ConfigureAdditionalPm() EhciPciMmBase = 0x%x \n",EhciPciMmBase)); + Buffer32 = MmioRead32(EhciPciMmBase + R_PCH_EHCI_PWR_CNTL_STS); + DEBUG ((EFI_D_INFO, "ConfigureAdditionalPm() R_PCH_EHCI_PWR_CNTL_STS = 0x%x \n",Buffer32)); + } +} + +#if defined SUPPORT_LVDS_DISPLAY && SUPPORT_LVDS_DISPLAY + +#endif + + +EFI_STATUS +EFIAPI +TristateLpcGpioS0i3Config ( + UINT32 Gpio_Mmio_Offset, + UINT32 Gpio_Pin_Num, + CFIO_PNP_INIT* Gpio_Conf_Data + ) +{ + + UINT32 index; + UINT32 mmio_reg; + UINT32 mmio_val; + + DEBUG ((DEBUG_INFO, "TristateLpcGpioS0i3Config\n")); + + for(index=0; index < Gpio_Pin_Num; index++) + { + mmio_reg = IO_BASE_ADDRESS + Gpio_Mmio_Offset + Gpio_Conf_Data[index].offset; + + MmioWrite32(mmio_reg, Gpio_Conf_Data[index].val); + mmio_val = 0; + mmio_val = MmioRead32(mmio_reg); + + DEBUG ((EFI_D_INFO, "Set MMIO=0x%08x PAD_VAL = 0x%08x,\n", mmio_reg, mmio_val)); + } + + return EFI_SUCCESS; +} + + +EFI_BOOT_SCRIPT_SAVE_PROTOCOL *mBootScriptSave; + +/** + Event Notification during exit boot service to enabel ACPI mode + + Disable SW SMI Timer, SMI from USB & Intel Specific USB 2 + + Clear all ACPI event status and disable all ACPI events + Disable PM sources except power button + Clear status bits + + Guarantee day-of-month alarm is invalid (ACPI 5.0 Section 4.8.2.4 "Real Time Clock Alarm") + + Update EC to disable SMI and enable SCI + + Enable SCI + + Enable PME_B0_EN in GPE0a_EN + + @param Event - EFI Event Handle + @param Context - Pointer to Notify Context + + @retval Nothing + +**/ +VOID +EFIAPI +EnableAcpiCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT32 RegData32; + UINT16 Pm1Cnt; + UINT16 AcpiBase; + UINT32 Gpe0aEn; + + AcpiBase = MmioRead16 ( + PchPciDeviceMmBase (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC) + R_PCH_LPC_ACPI_BASE + ) & B_PCH_LPC_ACPI_BASE_BAR; + + DEBUG ((EFI_D_INFO, "EnableAcpiCallback: AcpiBase = %x\n", AcpiBase)); + + // + // Disable SW SMI Timer, SMI from USB & Intel Specific USB 2 + // + RegData32 = IoRead32(AcpiBase + R_PCH_SMI_EN); + RegData32 &= ~(B_PCH_SMI_EN_SWSMI_TMR | B_PCH_SMI_EN_LEGACY_USB2 | B_PCH_SMI_EN_INTEL_USB2); + IoWrite32(AcpiBase + R_PCH_SMI_EN, RegData32); + + RegData32 = IoRead32(AcpiBase + R_PCH_SMI_STS); + RegData32 |= B_PCH_SMI_STS_SWSMI_TMR; + IoWrite32(AcpiBase + R_PCH_SMI_STS, RegData32); + + // + // Disable PM sources except power button + // power button is enabled only for PCAT. Disabled it on Tablet platform + // + + IoWrite16(AcpiBase + R_PCH_ACPI_PM1_EN, B_PCH_ACPI_PM1_EN_PWRBTN); + IoWrite16(AcpiBase + R_PCH_ACPI_PM1_STS, 0xffff); + + // + // Guarantee day-of-month alarm is invalid (ACPI 5.0 Section 4.8.2.4 "Real Time Clock Alarm") + // Clear Status D reg VM bit, Date of month Alarm to make Data in CMOS RAM is no longer Valid + // + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_D); + IoWrite8 (PCAT_RTC_DATA_REGISTER, 0x0); + + RegData32 = IoRead32(AcpiBase + R_PCH_ALT_GP_SMI_EN); + RegData32 &= ~(BIT7); + IoWrite32((AcpiBase + R_PCH_ALT_GP_SMI_EN), RegData32); + + // + // Enable SCI + // + Pm1Cnt = IoRead16(AcpiBase + R_PCH_ACPI_PM1_CNT); + Pm1Cnt |= B_PCH_ACPI_PM1_CNT_SCI_EN; + IoWrite16(AcpiBase + R_PCH_ACPI_PM1_CNT, Pm1Cnt); + + IoWrite8(0x80, 0xA0); //SW_SMI_ACPI_ENABLE + + // + // Enable PME_B0_EN in GPE0a_EN + // Caution: Enable PME_B0_EN must be placed after enabling SCI. + // Otherwise, USB PME could not be handled as SMI event since no handler is there. + // + Gpe0aEn = IoRead32 (AcpiBase + R_PCH_ACPI_GPE0a_EN); + Gpe0aEn |= B_PCH_ACPI_GPE0a_EN_PME_B0; + IoWrite32(AcpiBase + R_PCH_ACPI_GPE0a_EN, Gpe0aEn); + +} + +/** + + Routine Description: + + This is the standard EFI driver point for the Driver. This + driver is responsible for setting up any platform specific policy or + initialization information. + + @param ImageHandle Handle for the image of this driver. + @param SystemTable Pointer to the EFI System Table. + + @retval EFI_SUCCESS Policy decisions set. + +**/ +EFI_STATUS +EFIAPI +InitializePlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINTN VarSize; + EFI_HANDLE Handle = NULL; + + EFI_EVENT mEfiExitBootServicesEvent; + + // +mImageHandle = ImageHandle; + + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiSpeakerInterfaceProtocolGuid, + EFI_NATIVE_INTERFACE, + &mSpeakerInterface + ); + + Status = gBS->LocateProtocol ( + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + (VOID **) &mPciRootBridgeIo + ); + ASSERT_EFI_ERROR (Status); + + VarSize = sizeof(EFI_PLATFORM_INFO_HOB); + Status = gRT->GetVariable( + L"PlatformInfo", + &gEfiVlv2VariableGuid, + NULL, + &VarSize, + &mPlatformInfo + ); + + // + // Initialize Product Board ID variable + // + InitMfgAndConfigModeStateVar(); + InitPlatformBootMode(); + + // + // Install Observable protocol + // + InitializeObservableProtocol(); + + + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + NORMAL_SETUP_NAME, + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &mSystemConfiguration + ); + + + Status = EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + ReadyToBootFunction, + NULL, + &mReadyToBootEvent + ); + + // + // Create a ReadyToBoot Event to run the PME init process + // + Status = EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + InitPciDevPME, + NULL, + &mReadyToBootEvent + ); + // + // Create a ReadyToBoot Event to run enable PR0 and lock down + // + if(mSystemConfiguration.SpiRwProtect==1) { + Status = EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + SpiBiosProtectionFunction, + NULL, + &mReadyToBootEvent + ); + } + + ReportStatusCodeEx ( + EFI_PROGRESS_CODE, + EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_PLATFORM_DXE_STEP1, + 0, + &gEfiCallerIdGuid, + NULL, + NULL, + 0 + ); + +#if defined(SENSOR_INFO_VAR_SUPPORT) && SENSOR_INFO_VAR_SUPPORT != 0 + // + // Initialize Sensor Info variable + // + InitializeSensorInfoVariable(); +#endif + InitPchPlatformPolicy(&mPlatformInfo); + InitVlvPlatformPolicy(); + + // + // Add usb policy + // + InitPlatformUsbPolicy(); + InitSioPlatformPolicy(); + InitializeClockRouting(); + InitializeSlotInfo(); + InitTcoReset(); + + // + //Init ExI + // + InitExI(); + + ReportStatusCodeEx ( + EFI_PROGRESS_CODE, + EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_PLATFORM_DXE_STEP2, + 0, + &gEfiCallerIdGuid, + NULL, + NULL, + 0 + ); + + // + // Install PCI Bus Driver Hook + // + PciBusDriverHook(); + + InitItk(); + + ReportStatusCodeEx ( + EFI_PROGRESS_CODE, + EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_PLATFORM_DXE_STEP3, + 0, + &gEfiCallerIdGuid, + NULL, + NULL, + 0 + ); + + + // + // Initialize Password States and Callbacks + // + PchInitBeforeBoot(); + +#if defined SUPPORT_LVDS_DISPLAY && SUPPORT_LVDS_DISPLAY + +#endif + +#if defined(FIRMWARE_ID_BACKWARD_COMPATIBLE) && (FIRMWARE_ID_BACKWARD_COMPATIBLE != 0) + // + // Re-write Firmware ID if it is changed + // + InitFirmwareId(); +#endif + + ReportStatusCodeEx ( + EFI_PROGRESS_CODE, + EFI_COMPUTING_UNIT_CHIPSET | EFI_CU_PLATFORM_DXE_STEP4, + 0, + &gEfiCallerIdGuid, + NULL, + NULL, + 0 + ); + + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + EnableAcpiCallback, + NULL, + &gEfiEventExitBootServicesGuid, + &mEfiExitBootServicesEvent + ); + + +// +// Tristae Lpc pins at last moment +// +if (mSystemConfiguration.TristateLpc == 1) +{ +} + + return EFI_SUCCESS; +} + +/** + Source Or Destination with Length bytes. + + @param[in] Destination Target memory + @param[in] Source Source memory + @param[in] Length Number of bytes + + @retval None + +**/ +VOID +EfiOrMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +{ + CHAR8 *Destination8; + CHAR8 *Source8; + + if (Source < Destination) { + Destination8 = (CHAR8 *) Destination + Length - 1; + Source8 = (CHAR8 *) Source + Length - 1; + while (Length--) { + *(Destination8--) |= *(Source8--); + } + } else { + Destination8 = (CHAR8 *) Destination; + Source8 = (CHAR8 *) Source; + while (Length--) { + *(Destination8++) |= *(Source8++); + } + } +} + +VOID +PchInitBeforeBoot() +{ + // + // Saved SPI Opcode menu to fix EFI variable unable to write after S3 resume. + // + S3BootScriptSaveMemWrite ( + EfiBootScriptWidthUint32, + (UINTN)(SPI_BASE_ADDRESS + (R_PCH_SPI_OPMENU0)), + 1, + (VOID *)(UINTN)(SPI_BASE_ADDRESS + (R_PCH_SPI_OPMENU0))); + + S3BootScriptSaveMemWrite ( + EfiBootScriptWidthUint32, + (UINTN)(SPI_BASE_ADDRESS + (R_PCH_SPI_OPMENU1)), + 1, + (VOID *)(UINTN)(SPI_BASE_ADDRESS + (R_PCH_SPI_OPMENU1))); + + S3BootScriptSaveMemWrite ( + EfiBootScriptWidthUint16, + (UINTN)(SPI_BASE_ADDRESS + R_PCH_SPI_OPTYPE), + 1, + (VOID *)(UINTN)(SPI_BASE_ADDRESS + R_PCH_SPI_OPTYPE)); + + S3BootScriptSaveMemWrite ( + EfiBootScriptWidthUint16, + (UINTN)(SPI_BASE_ADDRESS + R_PCH_SPI_PREOP), + 1, + (VOID *)(UINTN)(SPI_BASE_ADDRESS + R_PCH_SPI_PREOP)); + + // + // Saved MTPMC_1 for S3 resume. + // + S3BootScriptSaveMemWrite ( + EfiBootScriptWidthUint32, + (UINTN)(PMC_BASE_ADDRESS + R_PCH_PMC_MTPMC1), + 1, + (VOID *)(UINTN)(PMC_BASE_ADDRESS + R_PCH_PMC_MTPMC1)); + return; +} + +VOID +EFIAPI +ReadyToBootFunction ( + EFI_EVENT Event, + VOID *Context + ) +{ + EFI_STATUS Status; + EFI_ISA_ACPI_PROTOCOL *IsaAcpi; + EFI_ISA_ACPI_DEVICE_ID IsaDevice; + UINTN Size; + UINT16 State; + EFI_TPM_MP_DRIVER_PROTOCOL *TpmMpDriver; + EFI_CPU_IO_PROTOCOL *CpuIo; + UINT8 Data; + UINT8 ReceiveBuffer [64]; + UINT32 ReceiveBufferSize; + + UINT8 TpmForceClearCommand [] = {0x00, 0xC1, + 0x00, 0x00, 0x00, 0x0A, + 0x00, 0x00, 0x00, 0x5D}; + UINT8 TpmPhysicalPresenceCommand [] = {0x00, 0xC1, + 0x00, 0x00, 0x00, 0x0C, + 0x40, 0x00, 0x00, 0x0A, + 0x00, 0x00}; + UINT8 TpmPhysicalDisableCommand [] = {0x00, 0xC1, + 0x00, 0x00, 0x00, 0x0A, + 0x00, 0x00, 0x00, 0x70}; + UINT8 TpmPhysicalEnableCommand [] = {0x00, 0xC1, + 0x00, 0x00, 0x00, 0x0A, + 0x00, 0x00, 0x00, 0x6F}; + UINT8 TpmPhysicalSetDeactivatedCommand [] = {0x00, 0xC1, + 0x00, 0x00, 0x00, 0x0B, + 0x00, 0x00, 0x00, 0x72, + 0x00}; + UINT8 TpmSetOwnerInstallCommand [] = {0x00, 0xC1, + 0x00, 0x00, 0x00, 0x0B, + 0x00, 0x00, 0x00, 0x71, + 0x00}; + + Size = sizeof(UINT16); + Status = gRT->GetVariable ( + VAR_EQ_FLOPPY_MODE_DECIMAL_NAME, + &gEfiNormalSetupGuid, + NULL, + &Size, + &State + ); + + // + // Disable Floppy Controller if needed + // + Status = gBS->LocateProtocol (&gEfiIsaAcpiProtocolGuid, NULL, (VOID **) &IsaAcpi); + if (!EFI_ERROR(Status) && (State == 0x00)) { + IsaDevice.HID = EISA_PNP_ID(0x604); + IsaDevice.UID = 0; + Status = IsaAcpi->EnableDevice(IsaAcpi, &IsaDevice, FALSE); + } + + // + // save LAN info to a variable + // + if (NULL != mPciLanInfo) { + gRT->SetVariable ( + L"PciLanInfo", + &gEfiPciLanInfoGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + mPciLanCount * sizeof(PCI_LAN_INFO), + mPciLanInfo + ); + } + + if (NULL != mPciLanInfo) { + gBS->FreePool (mPciLanInfo); + mPciLanInfo = NULL; + } + + + // + // Handle ACPI OS TPM requests here + // + Status = gBS->LocateProtocol ( + &gEfiCpuIoProtocolGuid, + NULL, + (VOID **)&CpuIo + ); + Status = gBS->LocateProtocol ( + &gEfiTpmMpDriverProtocolGuid, + NULL, + (VOID **)&TpmMpDriver + ); + if (!EFI_ERROR (Status)) + { + Data = ReadCmosBank1Byte (CpuIo, ACPI_TPM_REQUEST); + + // + // Clear pending ACPI TPM request indicator + // + WriteCmosBank1Byte (CpuIo, ACPI_TPM_REQUEST, 0x00); + if (Data != 0) + { + WriteCmosBank1Byte (CpuIo, ACPI_TPM_LAST_REQUEST, Data); + + // + // Assert Physical Presence for these commands + // + TpmPhysicalPresenceCommand [11] = 0x20; + ReceiveBufferSize = sizeof(ReceiveBuffer); + Status = TpmMpDriver->Transmit ( + TpmMpDriver, TpmPhysicalPresenceCommand, + sizeof (TpmPhysicalPresenceCommand), + ReceiveBuffer, &ReceiveBufferSize + ); + // + // PF PhysicalPresence = TRUE + // + TpmPhysicalPresenceCommand [11] = 0x08; + ReceiveBufferSize = sizeof(ReceiveBuffer); + Status = TpmMpDriver->Transmit ( + TpmMpDriver, TpmPhysicalPresenceCommand, + sizeof (TpmPhysicalPresenceCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + if (Data == 0x01) + { + // + // TPM_PhysicalEnable + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + Status = TpmMpDriver->Transmit ( + TpmMpDriver, TpmPhysicalEnableCommand, + sizeof (TpmPhysicalEnableCommand), + ReceiveBuffer, &ReceiveBufferSize + ); + } + if (Data == 0x02) + { + // + // TPM_PhysicalDisable + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + Status = TpmMpDriver->Transmit ( + TpmMpDriver, TpmPhysicalDisableCommand, + sizeof (TpmPhysicalDisableCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + } + if (Data == 0x03) + { + // + // TPM_PhysicalSetDeactivated=FALSE + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + TpmPhysicalSetDeactivatedCommand [10] = 0x00; + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalSetDeactivatedCommand, + sizeof (TpmPhysicalSetDeactivatedCommand), + ReceiveBuffer, &ReceiveBufferSize + ); + gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); + } + if (Data == 0x04) + { + // + // TPM_PhysicalSetDeactivated=TRUE + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + TpmPhysicalSetDeactivatedCommand [10] = 0x01; + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalSetDeactivatedCommand, + sizeof (TpmPhysicalSetDeactivatedCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + gRT->ResetSystem ( + EfiResetWarm, + EFI_SUCCESS, + 0, + NULL + ); + } + if (Data == 0x05) + { + // + // TPM_ForceClear + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmForceClearCommand, + sizeof (TpmForceClearCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + gRT->ResetSystem ( + EfiResetWarm, + EFI_SUCCESS, + 0, + NULL + ); + } + if (Data == 0x06) + { + // + // TPM_PhysicalEnable + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalEnableCommand, + sizeof (TpmPhysicalEnableCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + // + // TPM_PhysicalSetDeactivated=FALSE + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + TpmPhysicalSetDeactivatedCommand [10] = 0x00; + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalSetDeactivatedCommand, + sizeof (TpmPhysicalSetDeactivatedCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + gRT->ResetSystem ( + EfiResetWarm, + EFI_SUCCESS, + 0, + NULL + ); + } + if (Data == 0x07) + { + // + // TPM_PhysicalSetDeactivated=TRUE + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + TpmPhysicalSetDeactivatedCommand [10] = 0x01; + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalSetDeactivatedCommand, + sizeof (TpmPhysicalSetDeactivatedCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + // + // TPM_PhysicalDisable + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalDisableCommand, + sizeof (TpmPhysicalDisableCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + gRT->ResetSystem ( + EfiResetWarm, + EFI_SUCCESS, + 0, + NULL + ); + } + if (Data == 0x08) + { + // + // TPM_SetOwnerInstall=TRUE + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + TpmSetOwnerInstallCommand [10] = 0x01; + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmSetOwnerInstallCommand, + sizeof (TpmSetOwnerInstallCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + } + if (Data == 0x09) + { + // + // TPM_SetOwnerInstall=FALSE + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + TpmSetOwnerInstallCommand [10] = 0x00; + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmSetOwnerInstallCommand, + sizeof (TpmSetOwnerInstallCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + } + if (Data == 0x0A) + { + // + // TPM_PhysicalEnable + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalEnableCommand, + sizeof (TpmPhysicalEnableCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + // + // TPM_PhysicalSetDeactivated=FALSE + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + TpmPhysicalSetDeactivatedCommand [10] = 0x00; + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalSetDeactivatedCommand, + sizeof (TpmPhysicalSetDeactivatedCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + // + // Do TPM_SetOwnerInstall=TRUE on next reboot + // + + WriteCmosBank1Byte (CpuIo, ACPI_TPM_REQUEST, 0xF0); + + gRT->ResetSystem ( + EfiResetWarm, + EFI_SUCCESS, + 0, + NULL + ); + } + if (Data == 0x0B) + { + // + // TPM_SetOwnerInstall=FALSE + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + TpmSetOwnerInstallCommand [10] = 0x00; + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmSetOwnerInstallCommand, + sizeof (TpmSetOwnerInstallCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + // + // TPM_PhysicalSetDeactivated=TRUE + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + TpmPhysicalSetDeactivatedCommand [10] = 0x01; + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalSetDeactivatedCommand, + sizeof (TpmPhysicalSetDeactivatedCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + // + // TPM_PhysicalDisable + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalDisableCommand, + sizeof (TpmPhysicalDisableCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + gRT->ResetSystem ( + EfiResetWarm, + EFI_SUCCESS, + 0, + NULL + ); + } + if (Data == 0x0E) + { + // + // TPM_ForceClear + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmForceClearCommand, + sizeof (TpmForceClearCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + // + // TPM_PhysicalEnable + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalEnableCommand, + sizeof (TpmPhysicalEnableCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + // + // TPM_PhysicalSetDeactivated=FALSE + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + TpmPhysicalSetDeactivatedCommand [10] = 0x00; + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalSetDeactivatedCommand, + sizeof (TpmPhysicalSetDeactivatedCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + gRT->ResetSystem ( + EfiResetWarm, + EFI_SUCCESS, + 0, + NULL + ); + } + if (Data == 0xF0) + { + // + // Second part of ACPI TPM request 0x0A: OEM custom TPM_SetOwnerInstall=TRUE + // + ReceiveBufferSize = sizeof(ReceiveBuffer); + TpmSetOwnerInstallCommand [10] = 0x01; + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmSetOwnerInstallCommand, + sizeof (TpmSetOwnerInstallCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + WriteCmosBank1Byte (CpuIo, ACPI_TPM_LAST_REQUEST, 0x0A); + } + // + // Deassert Physical Presence + // + TpmPhysicalPresenceCommand [11] = 0x10; + ReceiveBufferSize = sizeof(ReceiveBuffer); + Status = TpmMpDriver->Transmit ( + TpmMpDriver, + TpmPhysicalPresenceCommand, + sizeof (TpmPhysicalPresenceCommand), + ReceiveBuffer, + &ReceiveBufferSize + ); + } + } + + return; +} + +/** + + Initializes manufacturing and config mode setting. + +**/ +VOID +InitMfgAndConfigModeStateVar() +{ + EFI_PLATFORM_SETUP_ID *BootModeBuffer; + VOID *HobList; + UINT16 State; + + // + // Variable initialization + // + State = FALSE; + + HobList = GetFirstGuidHob(&gEfiPlatformBootModeGuid); + if (HobList != NULL) { + BootModeBuffer = GET_GUID_HOB_DATA (HobList); + + // + // Check if in Manufacturing mode + // + if ( !CompareMem ( + &BootModeBuffer->SetupName, + MANUFACTURE_SETUP_NAME, + StrSize (MANUFACTURE_SETUP_NAME) + ) ) { + mMfgMode = TRUE; + } + + // + // Check if in safe mode + // + if ( !CompareMem ( + &BootModeBuffer->SetupName, + SAFE_SETUP_NAME, + StrSize (SAFE_SETUP_NAME) + ) ) { + State = TRUE; + } + } + +} + +/** + + Initializes manufacturing and config mode setting. + +**/ +VOID +InitPlatformBootMode() +{ + EFI_PLATFORM_SETUP_ID *BootModeBuffer; + VOID *HobList; + + HobList = GetFirstGuidHob(&gEfiPlatformBootModeGuid); + if (HobList != NULL) { + BootModeBuffer = GET_GUID_HOB_DATA (HobList); + mPlatformBootMode = BootModeBuffer->PlatformBootMode; + } +} + +/** + + Initializes ITK. + +**/ +VOID +InitItk( + ) +{ + EFI_STATUS Status; + UINT16 ItkModBiosState; + UINT8 Value; + UINTN DataSize; + UINT32 Attributes; + + // + // Setup local variable according to ITK variable + // + // + // Read ItkBiosModVar to determine if BIOS has been modified by ITK + // If ItkBiosModVar = 0 or if variable hasn't been initialized then BIOS has not been modified by ITK modified + // Set local variable VAR_EQ_ITK_BIOS_MOD_DECIMAL_NAME=0 if BIOS has not been modified by ITK + // + DataSize = sizeof (Value); + Status = gRT->GetVariable ( + ITK_BIOS_MOD_VAR_NAME, + &gItkDataVarGuid, + &Attributes, + &DataSize, + &Value + ); + if (Status == EFI_NOT_FOUND) { + // + // Variable not found, hasn't been initialized, intialize to 0 + // + Value=0x00; + // + // Write variable to flash. + // + gRT->SetVariable ( + ITK_BIOS_MOD_VAR_NAME, + &gItkDataVarGuid, + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (Value), + &Value + ); + +} + if ( (!EFI_ERROR (Status)) || (Status == EFI_NOT_FOUND) ) { + if (Value == 0x00) { + ItkModBiosState = 0x00; + } else { + ItkModBiosState = 0x01; + } + gRT->SetVariable ( + VAR_EQ_ITK_BIOS_MOD_DECIMAL_NAME, + &gEfiNormalSetupGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 2, + (void *)&ItkModBiosState + ); + } +} + +#if defined(FIRMWARE_ID_BACKWARD_COMPATIBLE) && (FIRMWARE_ID_BACKWARD_COMPATIBLE != 0) + +/** + + Initializes the BIOS FIRMWARE ID from the FIRMWARE_ID build variable. + +**/ +STATIC +VOID +InitFirmwareId( + ) +{ + EFI_STATUS Status; + CHAR16 FirmwareIdNameWithPassword[] = FIRMWARE_ID_NAME_WITH_PASSWORD; + + // + // First try writing the variable without a password in case we are + // upgrading from a BIOS without password protection on the FirmwareId + // + Status = gRT->SetVariable( + (CHAR16 *)&gFirmwareIdName, + &gFirmwareIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof( FIRMWARE_ID ) - 1, + FIRMWARE_ID + ); + + if (Status == EFI_INVALID_PARAMETER) { + + // + // Since setting the firmware id without the password failed, + // a password must be required. + // + Status = gRT->SetVariable( + (CHAR16 *)&FirmwareIdNameWithPassword, + &gFirmwareIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof( FIRMWARE_ID ) - 1, + FIRMWARE_ID + ); + } +} +#endif + +VOID +UpdateDVMTSetup( + ) +{ + // + // Workaround to support IIA bug. + // IIA request to change option value to 4, 5 and 7 relatively + // instead of 1, 2, and 3 which follow Lakeport Specs. + // Check option value, temporary hardcode GraphicsDriverMemorySize + // Option value to fulfill IIA requirment. So that user no need to + // load default and update setupvariable after update BIOS. + // Option value hardcoded as: 1 to 4, 2 to 5, 3 to 7. + // *This is for broadwater and above product only. + // + + SYSTEM_CONFIGURATION SystemConfiguration; + UINTN VarSize; + EFI_STATUS Status; + + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + NORMAL_SETUP_NAME, + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &SystemConfiguration + ); + + if((SystemConfiguration.GraphicsDriverMemorySize < 4) && !EFI_ERROR(Status) ) { + switch (SystemConfiguration.GraphicsDriverMemorySize){ + case 1: + SystemConfiguration.GraphicsDriverMemorySize = 4; + break; + case 2: + SystemConfiguration.GraphicsDriverMemorySize = 5; + break; + case 3: + SystemConfiguration.GraphicsDriverMemorySize = 7; + break; + default: + break; + } + + Status = gRT->SetVariable ( + NORMAL_SETUP_NAME, + &gEfiNormalSetupGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(SYSTEM_CONFIGURATION), + &SystemConfiguration + ); + } +} + +VOID +InitPlatformUsbPolicy ( + VOID + ) + +{ + EFI_HANDLE Handle; + EFI_STATUS Status; + + Handle = NULL; + + mUsbPolicyData.Version = (UINT8)USB_POLICY_PROTOCOL_REVISION_2; + mUsbPolicyData.UsbMassStorageEmulationType = mSystemConfiguration.UsbBIOSINT13DeviceEmulation; + if(mUsbPolicyData.UsbMassStorageEmulationType == 3) { + mUsbPolicyData.UsbEmulationSize = mSystemConfiguration.UsbBIOSINT13DeviceEmulationSize; + } else { + mUsbPolicyData.UsbEmulationSize = 0; + } + mUsbPolicyData.UsbZipEmulationType = mSystemConfiguration.UsbZipEmulation; + mUsbPolicyData.UsbOperationMode = HIGH_SPEED; + + // + // Some chipset need Period smi, 0 = LEGACY_PERIOD_UN_SUPP + // + mUsbPolicyData.USBPeriodSupport = LEGACY_PERIOD_UN_SUPP; + + // + // Some platform need legacyfree, 0 = LEGACY_FREE_UN_SUPP + // + mUsbPolicyData.LegacyFreeSupport = LEGACY_FREE_UN_SUPP; + + // + // Set Code base , TIANO_CODE_BASE =0x01, ICBD =0x00 + // + mUsbPolicyData.CodeBase = (UINT8)ICBD_CODE_BASE; + + // + // Some chispet 's LpcAcpibase are diffrent,set by platform or chipset, + // default is Ich acpibase =0x040. acpitimerreg=0x08. + mUsbPolicyData.LpcAcpiBase = 0x40; + mUsbPolicyData.AcpiTimerReg = 0x08; + + // + // Set for reduce usb post time + // + mUsbPolicyData.UsbTimeTue = 0x00; + mUsbPolicyData.InternelHubExist = 0x00; //TigerPoint doesn't have RMH + mUsbPolicyData.EnumWaitPortStableStall = 100; + + + Status = gBS->InstallProtocolInterface ( + &Handle, + &gUsbPolicyGuid, + EFI_NATIVE_INTERFACE, + &mUsbPolicyData + ); + ASSERT_EFI_ERROR(Status); + +} + +UINT8 +ReadCmosBank1Byte ( + IN EFI_CPU_IO_PROTOCOL *CpuIo, + IN UINT8 Index + ) +{ + UINT8 Data; + + CpuIo->Io.Write (CpuIo, EfiCpuIoWidthUint8, 0x72, 1, &Index); + CpuIo->Io.Read (CpuIo, EfiCpuIoWidthUint8, 0x73, 1, &Data); + return Data; +} + +VOID +WriteCmosBank1Byte ( + IN EFI_CPU_IO_PROTOCOL *CpuIo, + IN UINT8 Index, + IN UINT8 Data + ) +{ + CpuIo->Io.Write ( + CpuIo, + EfiCpuIoWidthUint8, + 0x72, + 1, + &Index + ); + CpuIo->Io.Write ( + CpuIo, + EfiCpuIoWidthUint8, + 0x73, + 1, + &Data + ); +} + diff --git a/Vlv2TbltDevicePkg/PlatformDxe/PlatformDxe.h b/Vlv2TbltDevicePkg/PlatformDxe/PlatformDxe.h new file mode 100644 index 0000000000..42197cab18 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/PlatformDxe.h @@ -0,0 +1,719 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PlatformDxe.h + +Abstract: + + Header file for Platform Initialization Driver. + + + +++*/ + +#ifndef _PLATFORM_DRIVER_H +#define _PLATFORM_DRIVER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Configuration.h" +#define _EFI_H_ //skip efi.h +#include "PchAccess.h" +#include "VlvAccess.h" +#include "BoardIdDecode.h" +#include "PlatformBaseAddresses.h" +#include "SetupMode.h" +#include "PlatformBootMode.h" +#include "CpuType.h" + +#define PCAT_RTC_ADDRESS_REGISTER 0x74 +#define PCAT_RTC_DATA_REGISTER 0x75 + +#define RTC_ADDRESS_SECOND_ALARM 0x01 +#define RTC_ADDRESS_MINUTE_ALARM 0x03 +#define RTC_ADDRESS_HOUR_ALARM 0x05 + +#define RTC_ADDRESS_REGISTER_A 0x0A +#define RTC_ADDRESS_REGISTER_B 0x0B +#define RTC_ADDRESS_REGISTER_C 0x0C +#define RTC_ADDRESS_REGISTER_D 0x0D + +#define B_RTC_ALARM_INT_ENABLE 0x20 +#define B_RTC_ALARM_INT_STATUS 0x20 + +#define B_RTC_DATE_ALARM_MASK 0x3F + +// +// Default CPU Alternate Duty Cycle (255=100%, 0=0%) +// +#define DEF_CPU_ALT_DUTY_CYCLE 0xFF + +#define MAX_ONBOARD_SATA_DEVICE 2 + +#define DXE_DEVICE_ENABLED 1 +#define DXE_DEVICE_DISABLED 0 + +#define AZALIA_MAX_LOOP_TIME 0x10000 + +// +// Platform driver GUID +// +#define EFI_PLATFORM_DRIVER_GUID \ + { 0x056E7324, 0xA718, 0x465b, 0x9A, 0x84, 0x22, 0x8F, 0x06, 0x64, 0x2B, 0x4F } + +#define PASSWORD_MAX_SIZE 20 +#define PLATFORM_NORMAL_MODE 0x01 +#define PLATFORM_SAFE_MODE 0x02 +#define PLATFORM_RECOVERY_MODE 0x04 +#define PLATFORM_MANUFACTURING_MODE 0x08 +#define PLATFORM_BACK_TO_BIOS_MODE 0x10 + +#define EFI_OEM_SPECIFIC 0x8000 +#define EFI_CU_PLATFORM_DXE_INIT (EFI_OEM_SPECIFIC | 0x00000011) +#define EFI_CU_PLATFORM_DXE_STEP1 (EFI_OEM_SPECIFIC | 0x00000012) +#define EFI_CU_PLATFORM_DXE_STEP2 (EFI_OEM_SPECIFIC | 0x00000013) +#define EFI_CU_PLATFORM_DXE_STEP3 (EFI_OEM_SPECIFIC | 0x00000014) +#define EFI_CU_PLATFORM_DXE_STEP4 (EFI_OEM_SPECIFIC | 0x00000015) +#define EFI_CU_PLATFORM_DXE_INIT_DONE (EFI_OEM_SPECIFIC | 0x00000016) + + +#define EFI_SECTION_STRING 0x1C +#define EFI_FORWARD_DECLARATION(x) typedef struct _##x x +#define PREFIX_BLANK 0x04 + +#pragma pack(1) + +typedef UINT64 EFI_BOARD_FEATURES; + +// +//BUGBUG: should remove these EDK hii definition once Hii transtion is done +// +typedef UINT16 STRING_REF; +typedef UINT16 EFI_FORM_LABEL; + +typedef enum { + EfiUserPassword, + EfiAdminPassword +} EFI_PASSWORD_TYPE; + +typedef struct { + CHAR16 TempPassword[PASSWORD_MAX_SIZE]; + CHAR16 EncodedPassword[PASSWORD_MAX_SIZE]; + VOID *PasswordLocation; + EFI_PASSWORD_TYPE PasswordType; +} EFI_PASSWORD_DATA; + +typedef struct { + CHAR8 AaNumber[7]; + UINT8 BoardId; + EFI_BOARD_FEATURES Features; + UINT16 SubsystemDeviceId; + UINT16 AudioSubsystemDeviceId; + UINT64 AcpiOemTableId; +} BOARD_ID_DECODE; + +typedef +EFI_STATUS +(EFIAPI *EFI_FORM_ROUTINE) ( + SYSTEM_CONFIGURATION *SetupBuffer + ); + +typedef struct{ + UINT16 DeviceNumber; + UINT16 FunctionNumber; +}PCI_DEVICE_FUNC_INFO; + +typedef struct{ + CHAR16 PortNumber[4]; + STRING_REF SataDeviceInfoStringId; +}SATA_DEVICE_STRING_INFO; + +typedef struct { + UINT16 Signature; + UINT8 Size; + UINT32 EntryPoint; + UINT8 Reserve[17]; + UINT16 PciDataOff; + UINT16 ExpansionOff; +} PNP_OPTION_ROM_HEADER; + +typedef struct { + UINT32 Signature; + UINT8 Revision; + UINT8 Length; + UINT16 NextHeader; + UINT8 Reserve; + UINT8 CheckSum; + UINT32 DeviceId; + UINT16 ManufactureStrOff; + UINT16 ProductStrOff; +} PNP_EXPANSION_HEADER; + +typedef struct { + BOOLEAN Enable; + UINT8 VerbTableNum; + UINT16 CodecSSID; + EFI_PHYSICAL_ADDRESS HDABar; + EFI_PHYSICAL_ADDRESS UpperHDABar; + UINT8 SDIPresent; + BOOLEAN Pme; + BOOLEAN LegacyFrontPanelAudio; + BOOLEAN HighDefinitionFrontPanelAudio; +} EFI_AZALIA_S3; + +// +//following structs are from R8. Remove them once R8->R9 transition is done +// +typedef struct { + CHAR16 *OptionString; // Passed in string to generate a token for in a truly dynamic form creation + STRING_REF StringToken; // This is used when creating a single op-code without generating a StringToken (have one already) + UINT16 Value; + UINT8 Flags; + UINT16 Key; +} IFR_OPTION; + + + +typedef struct { + UINT8 Number; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; +} PANEL_RESOLUTION; + +#pragma pack() + +// +// Prototypes +// +EFI_STATUS +EFIAPI +EfiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +ProcessEventLog ( + ); + +EFI_STATUS +FindDataRecords ( + ); + +EFI_STATUS +ProcessPasswords( + ); + +VOID +MemorySetup( + ); + + +UINTN +EfiValueToString ( + IN OUT CHAR16 *Buffer, + IN INT64 Value, + IN UINTN Flags, + IN UINTN Width + ); + +VOID +EFIAPI +ReadyToBootFunction ( + EFI_EVENT Event, + VOID *Context + ); + +VOID +InstallHiiDataAndGetSettings( + IN EFI_HII_STRING_PACK *StringPack, + // + ... // 0 or more of => IN EFI_HII_IFR_PACK *IfrPack, + // Terminate list with NULL + // + ); + +EFI_STATUS +ReadOrInitSetupVariable( + IN UINTN RequiredVariableSize, + IN UINTN RequiredPasswordSize, + IN VOID *DefaultData, + IN VOID *MfgDefaultData, + OUT VOID *SetupVariableData, + OUT VOID *SystemPassword + ); + +VOID +EfiLogicalOrMem( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ); + +EFI_STATUS +GetStringFromToken ( + IN EFI_GUID *ProducerGuid, + IN STRING_REF Token, + OUT CHAR16 **String + ); + +UINT32 +ConvertBase2ToRaw ( + IN EFI_EXP_BASE2_DATA *Data); + +UINT32 +ConvertBase10ToRaw ( + IN EFI_EXP_BASE10_DATA *Data); + +CHAR16 * +GetStringById ( + IN STRING_REF Id, + EFI_HII_HANDLE StringPackHandle + ); + +VOID +EFIAPI +SetupDataFilter ( + IN EFI_EVENT Event, + IN VOID* Context + ); + +VOID +EFIAPI +IdeDataFilter ( + IN EFI_EVENT Event, + IN VOID* Context + ); + +VOID +EFIAPI +UpdateAhciRaidDiskInfo ( + IN EFI_EVENT Event, + IN VOID* Context + ); + +VOID +EFIAPI +EventLogFilter ( + IN EFI_EVENT Event, + IN VOID* Context + ); + +VOID +SwapEntries ( + IN CHAR8 *Data + ); + +VOID +AsciiToUnicode ( + IN CHAR8 *AsciiString, + IN CHAR16 *UnicodeString + ); + +UINT16 +ConfigModeStateGet(); + +VOID +SetSkus(); + +VOID +CPUSetupItems(); + +EFI_STATUS +SecurityDriverCallback ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *Data, + OUT EFI_HII_CALLBACK_PACKET **Packet + ); + +VOID +SetPasswordState ( + ); + +VOID +EncodePassword ( + IN CHAR16 *Password + ); + +VOID +EFIAPI +PciBusEvent ( + IN EFI_EVENT Event, + IN VOID* Context + ); +VOID +AsfInitialize( + ); + +VOID +InitializeAsf ( + ); + +UINT8 +ReadCmosBank1Byte ( + IN EFI_CPU_IO_PROTOCOL *CpuIo, + IN UINT8 Index + ); + +VOID +WriteCmosBank1Byte ( + IN EFI_CPU_IO_PROTOCOL *CpuIo, + IN UINT8 Index, + IN UINT8 Data + ); + +VOID +InitializeBoardId ( + ); + +EFI_STATUS +InstallBootCallbackRoutine( + ); + +EFI_STATUS +InstallConfigurationCallbackRoutine( + ); + +EFI_STATUS +InstallPerformanceCallbackRoutine( + ); + +EFI_STATUS +InstallSecurityCallbackRoutine ( + ); + +EFI_STATUS +InstallMainCallbackRoutine ( + ); + +EFI_STATUS +MemoryConfigurationUpdate ( + UINT16 *Key, + EFI_FORM_LABEL *Label, + UINT16 *OpcodeCount, + UINT8 **OpcodeData, + EFI_FORM_ROUTINE *Routine + ); + +EFI_STATUS +MemoryConfigurationCallbackRoutine ( + SYSTEM_CONFIGURATION *SetupBuffer + ); + +EFI_STATUS +MemoryConfigurationCalculateSpeed( + SYSTEM_CONFIGURATION *SetupBuffer + ); + +VOID +UpdateMemoryString( + IN STRING_REF TokenToUpdate, + IN CHAR16 *NewString + ); + +VOID +InitFeaturePolicy ( + IN EFI_PLATFORM_INFO_HOB *PlatformInfo + ); + +VOID +InitializeSetupVarHide ( + ); + +VOID +PreparePCIePCISlotInformation( + VOID + ); + + +EFI_STATUS +BootConfigurationUpdate ( + IN OUT SYSTEM_CONFIGURATION *SystemConfiguration + ); + +EFI_STATUS +InitializeBootConfiguration( + VOID + ); + +UINT16 +GetStringSize( + IN CHAR16 *ThisString + ); + +UINT16 +GetDriveCount ( + IN STRING_REF *BootMap + ); + +CHAR16 * +GetBootString ( + IN STRING_REF Id, + OUT UINTN *Length + ); + +EFI_STATUS +BootCfgCreateTwoOptionOneOf( + IN UINT16 QuestionId, + IN EFI_FORM_LABEL Label, + IN STRING_REF OptionPrompt, + IN STRING_REF OptionHelp, + IN STRING_REF OptionOneString, + IN STRING_REF OptionTwoString, + IN UINT8 OptionOneFlags, + IN UINT8 OptionTwoFlags, + IN UINT16 KeyValueOne, + IN UINT16 KeyValueTwo + ); + +EFI_STATUS +ReplaceOpcodeWithText( + IN STRING_REF OptionPrompt, + IN STRING_REF OptionHelp, + IN STRING_REF OptionOneString, + IN EFI_FORM_LABEL Label + ); + +EFI_STATUS +CreateDriveBootOrderOpcode( + IN VOID *Data, + IN STRING_REF *BootMap, + IN EFI_FORM_LABEL Label, + IN UINT16 QuestionId, + IN STRING_REF OptionOneString, + IN STRING_REF OptionTwoString + ); + +VOID +SetHyperBootCfgFlags( + IN OUT SYSTEM_CONFIGURATION *SystemConfiguration + ); + +VOID +GetHyperBootCfgFlags( + IN OUT SYSTEM_CONFIGURATION *SystemConfiguration + ); + +VOID +PrepareBootCfgForHyperBoot( + IN OUT SYSTEM_CONFIGURATION *SystemConfiguration + ); + +BOOLEAN +BootCfgChanged( + IN SYSTEM_CONFIGURATION *SystemConfiguration + ); + +EFI_STATUS +InsertOpcodeAtIndex( + IN SYSTEM_CONFIGURATION *SystemConfiguration, + IN OUT IFR_OPTION *OptionList, + IN IFR_OPTION IfrOption, + IN UINT16 OptionCount + ); + +VOID +ConfigureBootOrderStrings( + IN SYSTEM_CONFIGURATION *SystemConfiguration + ); + +VOID +InitializeAllBootStrings( + VOID + ); + +VOID +SaveUsbCfgSettings( + IN OUT SYSTEM_CONFIGURATION *SystemConfiguration + ); + +VOID +RestoreUsbCfgSettings( + IN OUT SYSTEM_CONFIGURATION *SystemConfiguration + ); + +EFI_STATUS +UpdateBootDevicePriority( + IN OUT SYSTEM_CONFIGURATION *SystemConfiguration + ); + +EFI_STATUS +DisableHyperBoot( + IN OUT SYSTEM_CONFIGURATION *SystemConfiguration + ); + +BOOLEAN +CheckForUserPassword( + VOID + ); + +EFI_STATUS +EFIAPI +HyperBootPasswordCallback( + IN OUT VOID* Data + ); + +EFI_STATUS +EFIAPI +HyperBootF9Callback ( + IN VOID* Data + ); + +EFI_STATUS +InstallHiiEvents( + VOID + ); + +EFI_STATUS +EFIAPI +ProgramToneFrequency ( + IN EFI_SPEAKER_IF_PROTOCOL *This, + IN UINT16 Frequency + ); + +EFI_STATUS +EFIAPI +GenerateBeepTone ( + IN EFI_SPEAKER_IF_PROTOCOL *This, + IN UINTN NumberOfBeeps, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ); + +EFI_STATUS +InitializeObservableProtocol(); + +EFI_STATUS +PciBusDriverHook(); + +typedef struct _GOP_DISPLAY_BRIGHTNESS_PROTOCOL GOP_DISPLAY_BRIGHTNESS_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *GET_MAXIMUM_BRIGHTNESS_LEVEL) ( + IN GOP_DISPLAY_BRIGHTNESS_PROTOCOL *This, + OUT UINT32 *MaxBrightnessLevel + ); + + +typedef +EFI_STATUS +(EFIAPI *GET_CURRENT_BRIGHTNESS_LEVEL) ( + IN GOP_DISPLAY_BRIGHTNESS_PROTOCOL *This, + OUT UINT32 *MaxBrightnessLevel + ); + +typedef +EFI_STATUS +(EFIAPI *SET_BRIGHTNESS_LEVEL) ( + IN GOP_DISPLAY_BRIGHTNESS_PROTOCOL *This, + IN UINT32 BrightnessLevel + ); + +struct _GOP_DISPLAY_BRIGHTNESS_PROTOCOL { + UINT32 Revision; + GET_MAXIMUM_BRIGHTNESS_LEVEL GetMaxBrightnessLevel; + GET_CURRENT_BRIGHTNESS_LEVEL GetCurrentBrightnessLevel; + SET_BRIGHTNESS_LEVEL SetBrightnessLevel; +}; + +// +// Global externs +// +extern UINT8 MaintenanceBin[]; +extern UINT8 MainBin[]; +extern UINT8 ConfigurationBin[]; +extern UINT8 MemoryConfigurationBin[]; +extern UINT8 PerformanceBin[]; +extern UINT8 SecurityBin[]; +extern UINT8 BootBin[]; +extern UINT8 PowerBin[]; +extern UINT8 SystemSetupBin[]; + +extern VOID *mDxePlatformStringPack; +extern EFI_HII_PROTOCOL *mHii; +extern SYSTEM_CONFIGURATION mSystemConfiguration; +extern FRAMEWORK_EFI_HII_HANDLE mMaintenanceHiiHandle; +extern FRAMEWORK_EFI_HII_HANDLE mMainHiiHandle; +extern FRAMEWORK_EFI_HII_HANDLE mConfigurationHiiHandle; +extern FRAMEWORK_EFI_HII_HANDLE mPerformanceHiiHandle; +extern FRAMEWORK_EFI_HII_HANDLE mPowerHiiHandle; +extern FRAMEWORK_EFI_HII_HANDLE mBootHiiHandle; +extern FRAMEWORK_EFI_HII_HANDLE mSecurityHiiHandle; + +extern SYSTEM_PASSWORDS mSystemPassword; +extern EFI_PASSWORD_DATA mAdminPassword; +extern EFI_PASSWORD_DATA mUserPassword; + +extern EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *mPciRootBridgeIo; + +// +//extern EFI_REG_TABLE mSubsystemIdRegs[]; +// +extern UINT32 mSubsystemVidDid; +extern UINT32 mSubsystemAudioVidDid; + +extern UINT8 mBoardIdIndex; +extern BOOLEAN mFoundAANum; +extern EFI_BOARD_FEATURES mBoardFeatures; +extern UINT16 mSubsystemDeviceId; +extern UINT16 mSubsystemAudioDeviceId; +extern BOARD_ID_DECODE mBoardIdDecodeTable[]; +extern UINTN mBoardIdDecodeTableSize; + +extern UINT8 mSmbusRsvdAddresses[]; +extern UINT8 mNumberSmbusAddress; +extern BOOLEAN mMfgMode; +extern UINT32 mPlatformBootMode; +extern CHAR8 BoardAaNumber[]; + +extern EFI_GUID gEfiGlobalNvsAreaProtocolGuid; +#endif diff --git a/Vlv2TbltDevicePkg/PlatformDxe/PlatformDxe.inf b/Vlv2TbltDevicePkg/PlatformDxe/PlatformDxe.inf new file mode 100644 index 0000000000..6fa0700415 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/PlatformDxe.inf @@ -0,0 +1,145 @@ +#/*++ +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# Module Name: +# +# PlatformBB.inf +# +# Abstract: +# +# Component description file for platform DXE driver +# ------------------------------------------------------------------------------ +# Rev Date Name Description +# ------------------------------------------------------------------------------ +# R01 <04/22/2011> LB Update code for SIO83627UHG support. +# ------------------------------------------------------------------------------ +# +#--*/ + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformDxe + FILE_GUID = 056E7324-A718-465b-9A84-228F06642B4F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + ENTRY_POINT = InitializePlatform + +[sources.common] + BoardId.c + BoardIdDecode.c + ClockControl.c + Platform.c + IchRegTable.c + IdccInfo.c + SioPlatformPolicy.c + IchPlatformPolicy.c + PciDevice.c + SlotConfig.c + IchTcoReset.c + SensorVar.c + LegacySpeaker.c + Observable/Observable.c + ExI.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + SecurityPkg/SecurityPkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + DxeServicesTableLib + PchPlatformLib + + DebugLib + HiiLib + PrintLib + UefiLib + S3BootScriptLib + ReportStatusCodeLib + EfiRegTableLib + BiosIdLib + BaseCryptLib + +[Guids] + gEfiBiosIdGuid + gEfiPlatformBootModeGuid + gEfiBoardFeaturesGuid + gItkDataVarGuid + gDmiDataGuid + gIdccDataHubGuid + gEfiPciLanInfoGuid + gEfiNormalSetupGuid + gEfiGlobalVariableGuid + gEfiEventExitBootServicesGuid + gEfiVlv2VariableGuid + gEfiSecureBootEnableDisableGuid + +[Protocols] + gEfiPciRootBridgeIoProtocolGuid # CONSUMES ## GUID + gEfiVariableArchProtocolGuid + gEfiVariableWriteArchProtocolGuid + gEfiHiiConfigAccessProtocolGuid + gEfiBootScriptSaveProtocolGuid + gEfiCpuIoProtocolGuid + gEfiDevicePathProtocolGuid + gEfiDiskInfoProtocolGuid + gEfiPs2PolicyProtocolGuid + gEfiIsaAcpiProtocolGuid + gEfiDataHubProtocolGuid + gEfiPciIoProtocolGuid + gDxePchPlatformPolicyProtocolGuid + gEfiTpmMpDriverProtocolGuid + gEfiLpcWpce791PolicyProtocolGuid + gUsbPolicyGuid + gEfiSpeakerInterfaceProtocolGuid + gDxeVlvPlatformPolicyGuid + gEfiSmbiosSlotPopulationGuid + gObservableProtocolGuid + gEfiCk505ClockPlatformInfoGuid + gEfiLpcWpc83627PolicyProtocolGuid + gEfiTcoResetProtocolGuid + gEfiWatchdogTimerDriverProtocolGuid + gEfiPlatformIdeInitProtocolGuid + gEfiGlobalNvsAreaProtocolGuid + gEfiCpuIo2ProtocolGuid + gIgdOpRegionProtocolGuid + +[Pcd.common] + gPlatformModuleTokenSpaceGuid.PcdPBTNDisableInterval + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress + gPlatformModuleTokenSpaceGuid.PcdFlashMicroCodeAddress + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFastPS2Detection + +[Depex] + gEfiPciRootBridgeIoProtocolGuid AND + gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid AND + gEfiBootScriptSaveProtocolGuid AND + gEfiCpuIoProtocolGuid AND + gDxePchPlatformPolicyProtocolGuid AND + gEfiGlobalNvsAreaProtocolGuid + + diff --git a/Vlv2TbltDevicePkg/PlatformDxe/SensorVar.c b/Vlv2TbltDevicePkg/PlatformDxe/SensorVar.c new file mode 100644 index 0000000000..27f742b807 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/SensorVar.c @@ -0,0 +1,117 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + SensorVar.c + +Abstract: + + Initialization for the Sensor Info variable. + +Revision History + +--*/ + +#include "PlatformDxe.h" +#include "Guid/SensorInfoVariable.h" + +// +// Sensor Information (board specific) +// + +#define TEMPERATURE_SENSORS_COUNT 4 +#define VOLTAGE_SENSORS_COUNT 6 +#define FAN_SENSORS_COUNT 4 +#define FAN_CONTROLLERS_COUNT 3 + +TYPEDEF_TEMP_SENSOR_SECTION(TEMPERATURE_SENSORS_COUNT); +TYPEDEF_VOLT_SENSOR_SECTION(VOLTAGE_SENSORS_COUNT); +TYPEDEF_FAN_SENSOR_SECTION(FAN_SENSORS_COUNT); +TYPEDEF_FAN_CONTROLLER_SECTION(FAN_CONTROLLERS_COUNT); +TYPEDEF_SENSOR_INFO_VAR; + +SENSOR_INFO_VAR mSensorInfoData = +{ + // + // Temperature Sensors + // + TEMPERATURE_SENSORS_COUNT, + { + { 0, 3, CPU_CORE_TEMPERATURE, TRUE }, + { 0, 1, MOTHERBOARD_AMBIENT_TEMPERATURE, FALSE }, + { 0, 2, VR_TEMPERATURE, FALSE }, + { 0, 0, IOH_TEMPERATURE, FALSE } + }, + + // + // Voltage Sensors + // + VOLTAGE_SENSORS_COUNT, + { + { 0, 0, PLUS_12_VOLTS }, + { 0, 1, PLUS_5_VOLTS }, + { 0, 2, PLUS_3P3_VOLTS }, + { 0, 3, MCH_VCC_VOLTAGE }, + { 0, 4, CPU_1_VCCP_VOLTAGE }, + { 0, 5, CPU_VTT_VOLTAGE } + }, + + // + // Fan Speed Sensors + // + FAN_SENSORS_COUNT, + { + { 0, 0, CPU_COOLING_FAN, FAN_4WIRE, 0 }, + { 0, 1, AUX_COOLING_FAN, FAN_4WIRE, 1 }, + { 0, 2, CHASSIS_INLET_FAN, FAN_3WIRE_VOLTAGE, 1 }, + { 0, 3, CHASSIS_OUTLET_FAN, FAN_3WIRE_VOLTAGE, 2 } + }, + + // + // Fan Speed Controllers + // + FAN_CONTROLLERS_COUNT, + { + { 0, 0, CPU_COOLING_FAN, { 0, 0xff, 0xff, 0xff } }, + { 0, 1, CHASSIS_COOLING_FAN, { 1, 2, 0xff, 0xff } }, + { 0, 2, CHASSIS_COOLING_FAN, { 3, 0xff, 0xff, 0xff } } + } +}; + +/** + + Write the Sensor Info variable if it does not already exist. + +**/ +VOID +InitializeSensorInfoVariable ( + ) +{ + // + // Set the Sensor Info variable. If it already exists and the data matches, + // the variable driver will simply return without writing; otherwise, the + // driver will write the variable. + // + gRT->SetVariable ( + gEfiSensorInfoVarNameWithPassword, + &gEfiSensorInfoVarGuid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (SENSOR_INFO_VAR), + &mSensorInfoData + ); +} + diff --git a/Vlv2TbltDevicePkg/PlatformDxe/SioPlatformPolicy.c b/Vlv2TbltDevicePkg/PlatformDxe/SioPlatformPolicy.c new file mode 100644 index 0000000000..da006279ce --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/SioPlatformPolicy.c @@ -0,0 +1,87 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + SioPlatformPolicy.c + +Abstract: + + Sio Platform Policy Setting. + + +--*/ + +#include "PlatformDxe.h" +#include + + +EFI_WPC83627_POLICY_PROTOCOL mSio83627PolicyData = { + { EFI_WPC83627_COM1_ENABLE, // Com1 + EFI_WPC83627_LPT1_ENABLE, // Lpt1 + EFI_WPC83627_FDD_DISABLE, // Floppy + EFI_WPC83627_FDD_WRITE_ENABLE, // FloppyWriteProtect + EFI_WPC83627_RESERVED_DEFAULT, // Port80 + EFI_WPC83627_ECIR_DISABLE, // CIR + EFI_WPC83627_PS2_KBC_ENABLE, // Ps2Keyboard + EFI_WPC83627_RESERVED_DEFAULT, // Ps2Mouse + EFI_WPC83627_COM2_ENABLE, // Com2 + EFI_WPC83627_COM3_ENABLE, // Com3 + EFI_WPC83627_COM4_ENABLE, // Com4 + EFI_WPC83627_RESERVED_DEFAULT, // Dac + 0x00 // Rsvd + }, + LptModeEcp, // LptMode +}; + +/** + + Publish the platform SIO policy setting. + + @retval EFI_SUCCESS + +**/ +VOID +InitSioPlatformPolicy( + ) +{ + + EFI_HANDLE Handle; + EFI_STATUS Status; + + Handle = NULL; + + if((mSystemConfiguration.Serial) || (mBoardFeatures & B_BOARD_FEATURES_SIO_NO_COM1)) { + mSio83627PolicyData.DeviceEnables.Com1 = EFI_WPC83627_COM1_DISABLE; + } + + if((mSystemConfiguration.Serial2) || ((mBoardFeatures & B_BOARD_FEATURES_SIO_COM2)==0)) { + mSio83627PolicyData.DeviceEnables.Com2 = EFI_WPC83627_COM2_DISABLE; + } + + mSio83627PolicyData.LptMode = mSystemConfiguration.ParallelMode; + if((!mSystemConfiguration.Parallel) || (mBoardFeatures & B_BOARD_FEATURES_SIO_NO_PARALLEL)) { + mSio83627PolicyData.DeviceEnables.Lpt1 = EFI_WPC83627_LPT1_DISABLE; + } + + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiLpcWpc83627PolicyProtocolGuid, + EFI_NATIVE_INTERFACE, + &mSio83627PolicyData + ); + ASSERT_EFI_ERROR(Status); + +} + diff --git a/Vlv2TbltDevicePkg/PlatformDxe/SlotConfig.c b/Vlv2TbltDevicePkg/PlatformDxe/SlotConfig.c new file mode 100644 index 0000000000..c0c752601f --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/SlotConfig.c @@ -0,0 +1,153 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + SlotConfig.c + +Abstract: + + Sets platform/SKU specific expansion slot information. + + + +--*/ +#include "SlotConfig.h" + +// +// Implementation +// +VOID +InitializeSlotInfo ( + ) +{ + UINT16 BusSaveState; + UINT16 Vendor; + UINT8 CurrentBus; + UINTN i; + UINTN j; + EFI_HANDLE Handle; + EFI_STATUS Status; + BOOLEAN RunNext; + + // + // Loop through the slot table and see if any slots have cards in them + // + for (i = 0; i < mSlotBridgeTableSize; i++) { + // + // Initialize variable + // + RunNext = FALSE; + + // + // Hide mini PCIe slots per SKU + // + for (j = 0; j < mSlotInformation.NumberOfEntries; j++) { + if (mSlotInformation.SlotEntries[j].SmbiosSlotId == mSlotBridgeTable[i].SmbiosSlotId) { + if ((mSlotInformation.SlotEntries[j].SmbiosSlotId == 0x02) && + (mBoardFeatures & B_BOARD_FEATURES_NO_MINIPCIE) + ) { + mSlotInformation.SlotEntries[j].Disabled = TRUE; + RunNext = TRUE; + } + break; + } + } + + if (RunNext) { + // + // Skip slot device detection since the slot is disabled. + // + continue; + } + + // + // Check to see if the bridge has a bus number and assign one if not + // + BusSaveState = MmPci16 ( + 0, + mSlotBridgeTable[i].Bus, + mSlotBridgeTable[i].Dev, + mSlotBridgeTable[i].Function, + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET + ); + if (BusSaveState == 0) { + // + // Assign temp bus number + // + MmPci16 ( + 0, + mSlotBridgeTable[i].Bus, + mSlotBridgeTable[i].Dev, + mSlotBridgeTable[i].Function, + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET + ) = DEF_BUS_CONFIG; + CurrentBus = DEF_BUS; + } else if (BusSaveState == 0xFFFF) { + // + // Bridge is disabled so continue with next entry in the table + // + continue; + } else { + // + // Use existing bus number + // + CurrentBus = (UINT8) BusSaveState & 0xFF; + } + + // + // Check to see if a device is behind the bridge + // + Vendor = MmPci16 ( + 0, + CurrentBus, + mSlotBridgeTable[i].TargetDevice, + 0, + 0 + ); + if (Vendor != 0xFFFF) { + // + // Device found so make sure the slot is marked that way + // + for (j = 0; j < mSlotInformation.NumberOfEntries; j++) { + if (mSlotInformation.SlotEntries[j].SmbiosSlotId == mSlotBridgeTable[i].SmbiosSlotId) { + mSlotInformation.SlotEntries[j].InUse = TRUE; + break; + } + } + } + + // + // Restore previous bus information + // + if (BusSaveState == 0) { + MmPci16 ( + 0, + mSlotBridgeTable[i].Bus, + mSlotBridgeTable[i].Dev, + mSlotBridgeTable[i].Function, + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET + ) = 0; + } + } + + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiSmbiosSlotPopulationGuid, + EFI_NATIVE_INTERFACE, + &mSlotInformation + ); + ASSERT_EFI_ERROR(Status); + +} diff --git a/Vlv2TbltDevicePkg/PlatformDxe/SlotConfig.h b/Vlv2TbltDevicePkg/PlatformDxe/SlotConfig.h new file mode 100644 index 0000000000..97380dbaa8 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformDxe/SlotConfig.h @@ -0,0 +1,85 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + SlotConfig.c + +Abstract: + + Sets platform/SKU specific expansion slot information. + + + + +--*/ + +#include "PlatformDxe.h" +#include +#include + + +// +// Default bus number for the bridge +// +#define DEF_BUS_CONFIG 0x0101 +#define DEF_BUS 0x01 + +// +// Data structures for slot information +// +typedef struct { + UINT16 SmbiosSlotId; + UINT8 Bus; + UINT8 Dev; + UINT8 Function; + UINT8 TargetDevice; +} EFI_PCI_SLOT_BRIDGE_INFO; + +// +// Product specific bridge to slot routing information +// +EFI_PCI_SLOT_BRIDGE_INFO mSlotBridgeTable[] = { + { + 0x01, //PCIe x1 ICH (Bridge B0:D28:F1) + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2, + 0 + } +}; + +UINTN mSlotBridgeTableSize = + sizeof(mSlotBridgeTable) / sizeof(EFI_PCI_SLOT_BRIDGE_INFO); + +// +// Slot entry table for IBX RVP +// +EFI_SMBIOS_SLOT_ENTRY mSlotEntries[] = { + {0x06, FALSE, TRUE}, // PCIe x16 Slot 1 (NOT USED) + {0x04, FALSE, TRUE}, // PCIe x16 Slot 2 (NOT USED) + {0x03, FALSE, TRUE}, // PCIe x4 Slot (NOT USED) + {0x02, FALSE, FALSE}, // Mini PCIe x1 Slot + {0x15, FALSE, TRUE}, // PCIe x1 Slot 2 (NOT USED) + {0x16, FALSE, TRUE}, // PCIe x1 Slot 3 (NOT USED) + {0x07, FALSE, FALSE}, // PCI Slot 1 + {0x18, FALSE, TRUE}, // PCI Slot 2 (NOT USED) + {0x17, FALSE, TRUE}, // PCI Slot 3 (NOT USED) +}; + +EFI_SMBIOS_SLOT_POPULATION_INFO mSlotInformation = { + sizeof(mSlotEntries) / sizeof(EFI_SMBIOS_SLOT_ENTRY), + mSlotEntries +}; + + diff --git a/Vlv2TbltDevicePkg/PlatformGopPolicy/PlatformGopPolicy.c b/Vlv2TbltDevicePkg/PlatformGopPolicy/PlatformGopPolicy.c new file mode 100644 index 0000000000..59c73c62ba --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformGopPolicy/PlatformGopPolicy.c @@ -0,0 +1,196 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +--*/ + +/** @file +**/ + +#include +#include +#include +#include + +#include +#include +#include + +EFI_BOOT_SERVICES *gBS; + + +PLATFORM_GOP_POLICY_PROTOCOL mPlatformGOPPolicy; + +// +// Function implementations +// + +/** + The function will excute with as the platform policy, and gives + the Platform Lid Status. IBV/OEM can customize this code for their specific + policy action. + + @param CurrentLidStatus Gives the current LID Status + + @retval EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +GetPlatformLidStatus ( + OUT LID_STATUS *CurrentLidStatus +) +{ + *CurrentLidStatus = LidOpen; + + return EFI_SUCCESS; +} + +/** + The function will excute and gives the Video Bios Table Size and Address. + + @param VbtAddress Gives the Physical Address of Video BIOS Table + + @param VbtSize Gives the Size of Video BIOS Table + + @retval EFI_STATUS. + +**/ + +EFI_STATUS +EFIAPI +GetVbtData ( + OUT EFI_PHYSICAL_ADDRESS *VbtAddress, + OUT UINT32 *VbtSize +) +{ + EFI_STATUS Status; + UINTN FvProtocolCount; + EFI_HANDLE *FvHandles; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINTN Index; + UINT32 AuthenticationStatus; + + UINT8 *Buffer; + UINTN VbtBufferSize; + + Buffer = 0; + FvHandles = NULL; + + if (VbtAddress == NULL || VbtSize == NULL){ + return EFI_INVALID_PARAMETER; + } + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &FvProtocolCount, + &FvHandles + ); + + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < FvProtocolCount; Index++) { + Status = gBS->HandleProtocol ( + FvHandles[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + VbtBufferSize = 0; + Status = Fv->ReadSection ( + Fv, + &gBmpImageGuid, + EFI_SECTION_RAW, + 0, + (void **)&Buffer, + &VbtBufferSize, + &AuthenticationStatus + ); + + if (!EFI_ERROR (Status)) { + *VbtAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + *VbtSize = (UINT32)VbtBufferSize; + Status = EFI_SUCCESS; + break; + } + } + } else { + Status = EFI_NOT_FOUND; + } + + if (FvHandles != NULL) { + gBS->FreePool (FvHandles); + FvHandles = NULL; + } + + return Status; +} + +/** + Entry point for the Platform GOP Policy Driver. + + @param ImageHandle Image handle of this driver. + @param SystemTable Global system service table. + + @retval EFI_SUCCESS Initialization complete. + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver. + +**/ + +EFI_STATUS +EFIAPI +PlatformGOPPolicyEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + EFI_STATUS Status = EFI_SUCCESS; + SYSTEM_CONFIGURATION SystemConfiguration; + UINTN VarSize; + + + gBS = SystemTable->BootServices; + + gBS->SetMem ( + &mPlatformGOPPolicy, + sizeof (PLATFORM_GOP_POLICY_PROTOCOL), + 0 + ); + + mPlatformGOPPolicy.Revision = PLATFORM_GOP_POLICY_PROTOCOL_REVISION_01; + mPlatformGOPPolicy.GetPlatformLidStatus = GetPlatformLidStatus; + mPlatformGOPPolicy.GetVbtData = GetVbtData; + + // + // Install protocol to allow access to this Policy. + // + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + L"Setup", + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &SystemConfiguration + ); + ASSERT_EFI_ERROR(Status); + if (SystemConfiguration.GOPEnable == 1) + { + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gPlatformGOPPolicyGuid, + &mPlatformGOPPolicy, + NULL + ); + } + + return Status; +} diff --git a/Vlv2TbltDevicePkg/PlatformGopPolicy/PlatformGopPolicy.inf b/Vlv2TbltDevicePkg/PlatformGopPolicy/PlatformGopPolicy.inf new file mode 100644 index 0000000000..6fcf93b819 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformGopPolicy/PlatformGopPolicy.inf @@ -0,0 +1,56 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +## + + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformGOPPolicy + FILE_GUID = 9737D7CA-D869-45e5-A5EF-75D9438688DE + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PlatformGOPPolicyEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 +# + +[Sources.common] + PlatformGopPolicy.c + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec +[LibraryClasses] + BaseLib + DebugLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib +# DxeKscLib + +[Guids] + gBmpImageGuid + gEfiNormalSetupGuid + +[Protocols] + gEfiCpuIoProtocolGuid + gEfiFirmwareVolume2ProtocolGuid + gPlatformGOPPolicyGuid + +[Depex] + gEfiCpuIoProtocolGuid AND gEfiVariableArchProtocolGuid diff --git a/Vlv2TbltDevicePkg/PlatformInfoDxe/PlatformInfoDxe.c b/Vlv2TbltDevicePkg/PlatformInfoDxe/PlatformInfoDxe.c new file mode 100644 index 0000000000..6bf276246e --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInfoDxe/PlatformInfoDxe.c @@ -0,0 +1,161 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + PlatformInfoDxe.c + +Abstract: + Platform Info driver to public platform related HOB data + +--*/ + +#include "PlatformInfoDxe.h" + +/** + Entry point for the driver. + + This routine get the platform HOB data from PEI and publish + as Platform Info variable that can be accessed during boot service and + runtime. + + @param ImageHandle Image Handle. + @param SystemTable EFI System Table. + + @retval Status Function execution status. + +**/ +EFI_STATUS +EFIAPI +PlatformInfoInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_PLATFORM_INFO_HOB *PlatformInfoHobPtr; + EFI_PEI_HOB_POINTERS GuidHob; + EFI_PLATFORM_INFO_HOB TmpHob; + UINTN VarSize; + EFI_OS_SELECTION_HOB *OsSlectionHobPtr; + UINT8 Selection; + SYSTEM_CONFIGURATION SystemConfiguration; + UINT8 *LpssDataHobPtr; + UINT8 *LpssDataVarPtr; + UINTN i; + + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + NORMAL_SETUP_NAME, + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &SystemConfiguration + ); + + VarSize = sizeof(Selection); + Status = gRT->GetVariable( + L"OsSelection", + &gOsSelectionVariableGuid, + NULL, + &VarSize, + &Selection + ); + + if (EFI_ERROR(Status)) { + Selection = SystemConfiguration.ReservedO; + Status = gRT->SetVariable ( + L"OsSelection", + &gOsSelectionVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof(Selection), + &Selection + ); + } + + GuidHob.Raw = GetHobList (); + if (GuidHob.Raw != NULL) { + if ((GuidHob.Raw = GetNextGuidHob (&gOsSelectionVariableGuid, GuidHob.Raw)) != NULL) { + OsSlectionHobPtr = GET_GUID_HOB_DATA (GuidHob.Guid); + + if (OsSlectionHobPtr->OsSelectionChanged) { + SystemConfiguration.ReservedO = OsSlectionHobPtr->OsSelection; + + // + // Load Audio default configuration + // + SystemConfiguration.Lpe = OsSlectionHobPtr->Lpe; + SystemConfiguration.PchAzalia = OsSlectionHobPtr->PchAzalia; + + // + // Load LPSS and SCC default configurations + // + LpssDataHobPtr = &OsSlectionHobPtr->LpssData.LpssPciModeEnabled; + LpssDataVarPtr = &SystemConfiguration.LpssPciModeEnabled; + for (i = 0; i < sizeof(EFI_PLATFORM_LPSS_DATA); i++) { + *LpssDataVarPtr = *LpssDataHobPtr; + LpssDataVarPtr++; + LpssDataHobPtr++; + } + + SystemConfiguration.GOPEnable = TRUE; + + Status = gRT->SetVariable ( + NORMAL_SETUP_NAME, + &gEfiNormalSetupGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof(SYSTEM_CONFIGURATION), + &SystemConfiguration + ); + ASSERT_EFI_ERROR (Status); + } + } + } + + GuidHob.Raw = GetHobList (); + if (GuidHob.Raw == NULL) { + return EFI_NOT_FOUND; + } + + if ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformInfoGuid, GuidHob.Raw)) != NULL) { + PlatformInfoHobPtr = GET_GUID_HOB_DATA (GuidHob.Guid); + VarSize = sizeof(EFI_PLATFORM_INFO_HOB); + Status = gRT->GetVariable( + L"PlatformInfo", + &gEfiVlv2VariableGuid, + NULL, + &VarSize, + &TmpHob + ); + + if (EFI_ERROR(Status) || CompareMem (&TmpHob, PlatformInfoHobPtr, VarSize)) { + + // + // Write the Platform Info to volatile memory + // + Status = gRT->SetVariable( + L"PlatformInfo", + &gEfiVlv2VariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof(EFI_PLATFORM_INFO_HOB), + PlatformInfoHobPtr + ); + if (EFI_ERROR(Status)) { + return Status; + } + } + } + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/PlatformInfoDxe/PlatformInfoDxe.h b/Vlv2TbltDevicePkg/PlatformInfoDxe/PlatformInfoDxe.h new file mode 100644 index 0000000000..717d0c9dd5 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInfoDxe/PlatformInfoDxe.h @@ -0,0 +1,35 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + PlatformInfoDxe.h + +Abstract: + Platform Info Driver. + +--*/ + +#ifndef _PLATFORM_INFO_DRIVER_H_ +#define _PLATFORM_INFO_DRIVER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif diff --git a/Vlv2TbltDevicePkg/PlatformInfoDxe/PlatformInfoDxe.inf b/Vlv2TbltDevicePkg/PlatformInfoDxe/PlatformInfoDxe.inf new file mode 100644 index 0000000000..e507d498d5 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInfoDxe/PlatformInfoDxe.inf @@ -0,0 +1,57 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# Module Name: +# +# PlatformInfoDxe.inf +# +# Abstract: +# +# +--*/ + + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformInfoDxe + FILE_GUID = 025F738B-4EBD-4d55-B728-5F421B601F1F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PlatformInfoInit + +[sources] + PlatformInfoDxe.c + PlatformInfoDxe.h + +[Guids] + gEfiAcpiVariableGuid # ALWAYS_CONSUMED + gEfiPlatformInfoGuid # ALWAYS_CONSUMED + gEfiVlv2VariableGuid + gEfiNormalSetupGuid + gOsSelectionVariableGuid + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + +[LibraryClasses] + HobLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + +[Depex] + gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/BootMode.c b/Vlv2TbltDevicePkg/PlatformInitPei/BootMode.c new file mode 100644 index 0000000000..174d8e974e --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/BootMode.c @@ -0,0 +1,426 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + BootMode.c + +Abstract: + + EFI PEIM to provide the platform support functionality on the Thurley. + + +--*/ + +#include "PlatformEarlyInit.h" + + +#define NORMALMODE 0 +#define RECOVERYMODE 1 +#define SAFEMODE 2 +#define MANUFACTURINGMODE 3 + +#define GPIO_SSUS_OFFSET 0x2000 +#define PMU_PWRBTN_B_OFFSET 0x88 + +EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiBootInRecoveryModePpiGuid, + NULL +}; + +/** + Return the setting of the Bios configuration jumper + + @param VOID + + @retval RECOVERYMODE jumper set to recovery mode + @retval SAFEMODE jumper set to config mode + @retval NORMALMODE jumper in normal mode + +**/ +UINTN +GetConfigJumper( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ) +{ + // + // Do the Forced recovery detection based on logic chart above + // + if (IsRecoveryJumper(PeiServices, PlatformInfoHob)) { + return RECOVERYMODE; + } else { + return NORMALMODE; + } +} + +BOOLEAN +CheckIfRecoveryMode( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ) +{ + if (GetConfigJumper(PeiServices, PlatformInfoHob) == RECOVERYMODE) { + return TRUE; + } + return FALSE; +} + +BOOLEAN +CheckIfSafeMode( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ) +{ + if (GetConfigJumper(PeiServices, PlatformInfoHob) == SAFEMODE) { + return TRUE; + } + return FALSE; +} + +BOOLEAN +CheckIfManufacturingMode ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; + UINT32 Attributes; + UINTN DataSize; + CHAR16 VarName[] = MFGMODE_VARIABLE_NAME; + UINT8 MfgMode; + + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&Variable + ); + ASSERT_EFI_ERROR (Status); + + // + // Check if SW MMJ mode + // + Attributes = (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); + DataSize = sizeof (MFG_MODE_VAR); + + Status = Variable->GetVariable ( + Variable, + VarName, + &gMfgModeVariableGuid, + &Attributes, + &DataSize, + &MfgMode + ); + if (!(EFI_ERROR (Status))) { + return TRUE; + } + return FALSE; +} + +EFI_STATUS +UpdateBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + UINT16 SleepType; + CHAR16 *strBootMode; + PEI_CAPSULE_PPI *Capsule; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; + SYSTEM_CONFIGURATION SystemConfiguration; + UINTN VarSize; + volatile UINT32 GpioValue; + BOOLEAN IsFirstBoot; + UINT32 Data32; + + Status = (*PeiServices)->GetBootMode( + PeiServices, + &BootMode + ); + ASSERT_EFI_ERROR (Status); + if (BootMode == BOOT_IN_RECOVERY_MODE){ + return Status; + } + GetWakeupEventAndSaveToHob (PeiServices); + + // + // Let's assume things are OK if not told otherwise + // + BootMode = BOOT_WITH_FULL_CONFIGURATION; + + // + // When this boot is WDT reset, the system needs booting with CrashDump function eanbled. + // + Data32 = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_TCO_STS); + + // + // Check Power Button, click the power button, the system will boot in fast boot mode, + // if it is pressed and hold for a second, it will boot in FullConfiguration/setup mode. + // + GpioValue = MmioRead32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + PMU_PWRBTN_B_OFFSET); // The value of GPIOS_16 (PMU_PWRBTN_B) + if (((GpioValue & BIT0) != 0)&&((Data32 & B_PCH_TCO_STS_SECOND_TO) != B_PCH_TCO_STS_SECOND_TO)){ + IsFirstBoot = PcdGetBool(PcdBootState); + if (!IsFirstBoot){ + VarSize = sizeof (SYSTEM_CONFIGURATION); + ZeroMem (&SystemConfiguration, sizeof (SYSTEM_CONFIGURATION)); + + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&Variable + ); + ASSERT_EFI_ERROR (Status); + + // + // Use normal setup default from NVRAM variable, + // the Platform Mode (manufacturing/safe/normal) is handle in PeiGetVariable. + // + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = Variable->GetVariable ( + Variable, + L"Setup", + &gEfiSetupVariableGuid, + NULL, + &VarSize, + &SystemConfiguration + ); + + if (SystemConfiguration.FastBoot == 1) { + BootMode = BOOT_WITH_MINIMAL_CONFIGURATION; + } + } + } + + // + // Check if we need to boot in forced recovery mode + // + if (CheckIfRecoveryMode(PeiServices, PlatformInfoHob)) { + BootMode = BOOT_IN_RECOVERY_MODE; + } + + if (BootMode == BOOT_IN_RECOVERY_MODE) { + Status = (*PeiServices)->InstallPpi ( + PeiServices, + &mPpiListRecoveryBootMode + ); + ASSERT_EFI_ERROR (Status); + } else { + if (GetSleepTypeAfterWakeup (PeiServices, &SleepType)) { + switch (SleepType) { + case V_PCH_ACPI_PM1_CNT_S3: + BootMode = BOOT_ON_S3_RESUME; + + // + // Determine if we're in capsule update mode + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gPeiCapsulePpiGuid, + 0, + NULL, + (void **)&Capsule + ); + + if (Status == EFI_SUCCESS) { + if (Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES**)PeiServices) == EFI_SUCCESS) { + BootMode = BOOT_ON_FLASH_UPDATE; + } + } + + break; + + case V_PCH_ACPI_PM1_CNT_S4: + BootMode = BOOT_ON_S4_RESUME; + break; + + case V_PCH_ACPI_PM1_CNT_S5: + BootMode = BOOT_ON_S5_RESUME; + break; + } // switch (SleepType) + } + + // + // Check for Safe Mode + // + } + + switch (BootMode) { + case BOOT_WITH_FULL_CONFIGURATION: + strBootMode = L"BOOT_WITH_FULL_CONFIGURATION"; + break; + case BOOT_WITH_MINIMAL_CONFIGURATION: + strBootMode = L"BOOT_WITH_MINIMAL_CONFIGURATION"; + break; + case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES: + strBootMode = L"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES"; + break; + case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS: + strBootMode = L"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS"; + break; + case BOOT_WITH_DEFAULT_SETTINGS: + strBootMode = L"BOOT_WITH_DEFAULT_SETTINGS"; + break; + case BOOT_ON_S4_RESUME: + strBootMode = L"BOOT_ON_S4_RESUME"; + break; + case BOOT_ON_S5_RESUME: + strBootMode = L"BOOT_ON_S5_RESUME"; + break; + case BOOT_ON_S2_RESUME: + strBootMode = L"BOOT_ON_S2_RESUME"; + break; + case BOOT_ON_S3_RESUME: + strBootMode = L"BOOT_ON_S3_RESUME"; + break; + case BOOT_ON_FLASH_UPDATE: + strBootMode = L"BOOT_ON_FLASH_UPDATE"; + break; + case BOOT_IN_RECOVERY_MODE: + strBootMode = L"BOOT_IN_RECOVERY_MODE"; + break; + default: + strBootMode = L"Unknown boot mode"; + } // switch (BootMode) + + DEBUG ((EFI_D_ERROR, "Setting BootMode to %s\n", strBootMode)); + Status = (*PeiServices)->SetBootMode( + PeiServices, + BootMode + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Get sleep type after wakeup + + @param PeiServices Pointer to the PEI Service Table. + @param SleepType Sleep type to be returned. + + @retval TRUE A wake event occured without power failure. + @retval FALSE Power failure occured or not a wakeup. + +**/ +BOOLEAN +GetSleepTypeAfterWakeup ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT16 *SleepType + ) +{ + UINT16 Pm1Sts; + UINT16 Pm1Cnt; + UINT16 GenPmCon1; + GenPmCon1 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1); + + // + // Read the ACPI registers + // + Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS); + Pm1Cnt = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT); + + if ((GenPmCon1 & (B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR | B_PCH_PMC_GEN_PMCON_GEN_RST_STS)) || + (Pm1Sts & B_PCH_ACPI_PM1_STS_PRBTNOR)) { + // + // If power failure indicator, then don't attempt s3 resume. + // Clear PM1_CNT of S3 and set it to S5 as we just had a power failure, and memory has + // lost already. This is to make sure no one will use PM1_CNT to check for S3 after + // power failure. + // + if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) { + Pm1Cnt = ((Pm1Cnt & ~B_PCH_ACPI_PM1_CNT_SLP_TYP) | V_PCH_ACPI_PM1_CNT_S5); + IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, Pm1Cnt); + } + // + // Clear Wake Status (WAK_STS) + // + IoWrite16 ((ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS), B_PCH_ACPI_PM1_STS_WAK); + } + // + // Get sleep type if a wake event occurred and there is no power failure + // + if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) { + *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP; + return TRUE; + } else if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S4){ + *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP; + return TRUE; + } + return FALSE; +} + +VOID +SetPlatformBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ) +{ + EFI_PLATFORM_SETUP_ID PlatformSetupId; + + ZeroMem(&PlatformSetupId, sizeof (EFI_PLATFORM_SETUP_ID)); + + CopyMem (&PlatformSetupId.SetupGuid, + &gEfiNormalSetupGuid, + sizeof (EFI_GUID)); + + if (CheckIfRecoveryMode(PeiServices, PlatformInfoHob)) { + // + // Recovery mode + // + CopyMem (&PlatformSetupId.SetupName, + SAFE_SETUP_NAME, + StrSize (SAFE_SETUP_NAME)); + PlatformSetupId.PlatformBootMode = PLATFORM_RECOVERY_MODE; + } else if (CheckIfSafeMode(PeiServices, PlatformInfoHob)) { + // + // Safe mode also called config mode or maintenace mode. + // + CopyMem (&PlatformSetupId.SetupName, + SAFE_SETUP_NAME, + StrSize (SAFE_SETUP_NAME)); + PlatformSetupId.PlatformBootMode = PLATFORM_SAFE_MODE; + + } else if(0) { // else if (CheckIfManufacturingMode(PeiServices)) { + // + // Manufacturing mode + // + CopyMem (&PlatformSetupId.SetupName, + MANUFACTURE_SETUP_NAME, + StrSize (MANUFACTURE_SETUP_NAME)); + PlatformSetupId.PlatformBootMode = PLATFORM_MANUFACTURING_MODE; + + } else { + // + // Default to normal mode. + // + CopyMem (&PlatformSetupId.SetupName, + &NORMAL_SETUP_NAME, + StrSize (NORMAL_SETUP_NAME)); + PlatformSetupId.PlatformBootMode = PLATFORM_NORMAL_MODE; + } + + BuildGuidDataHob ( + &gEfiPlatformBootModeGuid, + &PlatformSetupId, + sizeof (EFI_PLATFORM_SETUP_ID) + ); + return; +} diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/CpuInitPeim.c b/Vlv2TbltDevicePkg/PlatformInitPei/CpuInitPeim.c new file mode 100644 index 0000000000..f75bacef48 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/CpuInitPeim.c @@ -0,0 +1,49 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + CpuInitPeim.c + +Abstract: + + Functions for LpcSio initilization + It is needed for early onboard LAN controller disable/enable in platform setup. + +--*/ + +#include "PlatformEarlyInit.h" + + +EFI_STATUS +PlatformCpuInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN SYSTEM_CONFIGURATION *SystemConfiguration, + IN EFI_PLATFORM_CPU_INFO *PlatformCpuInfo + ) +{ + BOOLEAN ResetRequired; + + // + // Variable initialization + // + ResetRequired = FALSE; + + + if (ResetRequired) { + CpuOnlyReset(PeiServices); + } + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/Dimm.c b/Vlv2TbltDevicePkg/PlatformInitPei/Dimm.c new file mode 100644 index 0000000000..e4dd2d68f0 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/Dimm.c @@ -0,0 +1,324 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + Dimm.c + +Abstract: + + PPI for reading SPD modules on DIMMs. + +--*/ + + +// +// Header Files +// +#include "Platformearlyinit.h" + +#define DIMM_SOCKETS 4 // Total number of DIMM sockets allowed on + // the platform +#define DIMM_SEGMENTS 1 // Total number of Segments Per DIMM. +#define MEMORY_CHANNELS 2 // Total number of memory channels + // populated on the system board +// +// Prototypes +// + +EFI_STATUS +EFIAPI +GetDimmState ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_PLATFORM_DIMM_PPI *This, + IN UINT8 Dimm, + OUT PEI_PLATFORM_DIMM_STATE *State + ); + +EFI_STATUS +EFIAPI +SetDimmState ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_PLATFORM_DIMM_PPI *This, + IN UINT8 Dimm, + IN PEI_PLATFORM_DIMM_STATE *State + ); + +EFI_STATUS +EFIAPI +ReadSpd ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_PLATFORM_DIMM_PPI *This, + IN UINT8 Dimm, + IN UINT8 Offset, + IN UINTN Count, + IN OUT UINT8 *Buffer + ); + +static PEI_PLATFORM_DIMM_PPI mGchDimmPpi = { + DIMM_SOCKETS, + DIMM_SEGMENTS, + MEMORY_CHANNELS, + GetDimmState, + SetDimmState, + ReadSpd +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiPlatformDimm = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiPlatformDimmPpiGuid, + &mGchDimmPpi +}; + + +// +// Functions +// + +/** + This function returns the current state of a single DIMM. Present indicates + that the DIMM slot is physically populated. Disabled indicates that the DIMM + should not be used. + + @param PeiServices PEI services table pointer + @param This PPI pointer + @param Dimm DIMM to read from + @param State Pointer to a return buffer to be updated with the current state + of the DIMM + + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +EFIAPI +GetDimmState ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_PLATFORM_DIMM_PPI *This, + IN UINT8 Dimm, + OUT PEI_PLATFORM_DIMM_STATE *State + ) +{ + EFI_STATUS Status; + UINT8 Buffer; + + PEI_ASSERT (PeiServices, (Dimm < This->DimmSockets)); + + // + // A failure here does not necessarily mean that no DIMM is present. + // Read a single byte. All we care about is the return status. + // + Status = ReadSpd ( + PeiServices, + This, + Dimm, + 0, + 1, + &Buffer + ); + + if (EFI_ERROR (Status)) { + State->Present = 0; + } else { + State->Present = 1; + } + + // + // BUGBUG: Update to check platform variable when it is available + // + State->Disabled = 0; + State->Reserved = 0; + + return EFI_SUCCESS; +} + +/** + + This function updates the state of a single DIMM. + + @param PeiServices PEI services table pointer + @param This PPI pointer + @param Dimm DIMM to set state for + @param State Pointer to the state information to set. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_UNSUPPORTED The function is not supported. + +**/ +EFI_STATUS +EFIAPI +SetDimmState ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_PLATFORM_DIMM_PPI *This, + IN UINT8 Dimm, + IN PEI_PLATFORM_DIMM_STATE *State + ) +{ + return EFI_UNSUPPORTED; +} + +/** + This function reads SPD information from a DIMM. + + PeiServices PEI services table pointer + This PPI pointer + Dimm DIMM to read from + Offset Offset in DIMM + Count Number of bytes + Buffer Return buffer + + @param EFI_SUCCESS The function completed successfully. + @param EFI_DEVICE_ERROR The DIMM being accessed reported a device error, + does not have an SPD module, or is not installed in + the system. + @retval EFI_TIMEOUT Time out trying to read the SPD module. + @retval EFI_INVALID_PARAMETER A parameter was outside the legal limits. + +**/ +EFI_STATUS +EFIAPI +ReadSpd ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_PLATFORM_DIMM_PPI *This, + IN UINT8 Dimm, + IN UINT8 Offset, + IN UINTN Count, + IN OUT UINT8 *Buffer + ) +{ + EFI_STATUS Status; + PEI_SMBUS_PPI *Smbus; + UINTN Index; + UINTN Index1; + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + EFI_SMBUS_DEVICE_COMMAND Command; + UINTN Length; + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPeiSmbusPpiGuid, // GUID + 0, // INSTANCE + NULL, // EFI_PEI_PPI_DESCRIPTOR + &Smbus // PPI + ); + ASSERT_PEI_ERROR (PeiServices, Status); + + switch (Dimm) { + case 0: + SlaveAddress.SmbusDeviceAddress = SMBUS_ADDR_CH_A_1 >> 1; + break; + case 1: + SlaveAddress.SmbusDeviceAddress = SMBUS_ADDR_CH_A_2 >> 1; + break; + case 2: + SlaveAddress.SmbusDeviceAddress = SMBUS_ADDR_CH_B_1 >> 1; + break; + case 3: + SlaveAddress.SmbusDeviceAddress = SMBUS_ADDR_CH_B_2 >> 1; + break; + default: + return EFI_INVALID_PARAMETER; + } + + Index = Count % 4; + if (Index != 0) { + // + // read the first serveral bytes to speed up following reading + // + for (Index1 = 0; Index1 < Index; Index1++) { + Length = 1; + Command = Offset + Index1; + Status = Smbus->Execute ( + PeiServices, + Smbus, + SlaveAddress, + Command, + EfiSmbusReadByte, + FALSE, + &Length, + &Buffer[Index1] + ); + if (EFI_ERROR(Status)) { + return Status; + } + } + } + + // + // Now collect all the remaining bytes on 4 bytes block + // + for (; Index < Count; Index += 2) { + Command = Index + Offset; + Length = 2; + Status = Smbus->Execute ( + PeiServices, + Smbus, + SlaveAddress, + Command, + EfiSmbusReadWord, + FALSE, + &Length, + &Buffer[Index] + ); + if (EFI_ERROR(Status)) { + return Status; + } + + Index += 2; + Command = Index + Offset; + Length = 2; + Status = Smbus->Execute ( + PeiServices, + Smbus, + SlaveAddress, + Command, + EfiSmbusReadWord, + FALSE, + &Length, + &Buffer[Index] + ); + if (EFI_ERROR(Status)) { + return Status; + } + } + return EFI_SUCCESS; +} + +/** + This function initializes the PEIM. It simply installs the DIMM PPI. + + @param FfsHeader Not used by this function + @param PeiServices Pointer to PEI services table + + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +EFIAPI +PeimInitializeDimm ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *SmbusPpi + ) +{ + EFI_STATUS Status; + + Status = (**PeiServices).InstallPpi ( + PeiServices, + &mPpiPlatformDimm + ); + ASSERT_PEI_ERROR (PeiServices, Status); + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/FlashMap.c b/Vlv2TbltDevicePkg/PlatformInitPei/FlashMap.c new file mode 100644 index 0000000000..282faa85ff --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/FlashMap.c @@ -0,0 +1,148 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +Module Name: + + FlashMap.c + +Abstract: + + Build GUIDed HOBs for platform specific flash map. + +--*/ + +#include "Efi.h" +#include "Pei.h" +#include "PeiLib.h" +#include "PeiLib.h" +#include "EfiFlashMap.h" +#include EFI_PROTOCOL_CONSUMER (FirmwareVolumeBlock) +#include EFI_GUID_DEFINITION (FlashMapHob) +#include EFI_GUID_DEFINITION (SystemNvDataGuid) +#include EFI_GUID_DEFINITION (FirmwareFileSystem) + +EFI_GUID mFvBlockGuid = EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID; +EFI_GUID mFfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID; +EFI_GUID mSystemDataGuid = EFI_SYSTEM_NV_DATA_HOB_GUID; + +static EFI_FLASH_AREA_DATA mFlashAreaData[] = { + // + // Variable area + // + { FixedPcdGet32 (PcdFlashNvStorageVariableBase), + FixedPcdGet32 (PcdFlashNvStorageVariableSize), + EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, + EFI_FLASH_AREA_EFI_VARIABLES }, + + // + // Boot block 2nd part + // + { FixedPcdGet32 (PcdFlashFvRecovery2Base), + FixedPcdGet32 (PcdFlashFvRecovery2Size), + EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, + EFI_FLASH_AREA_FTW_BACKUP }, + + // + // Recovery FV + // + { FixedPcdGet32 (PcdFlashFvRecoveryBase), + FixedPcdGet32 (PcdFlashFvRecoverySize), + EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV, + EFI_FLASH_AREA_RECOVERY_BIOS }, + + // + // Main FV + // + { FixedPcdGet32 (PcdFlashFvMainBase), + FixedPcdGet32 (PcdFlashFvMainSize), + EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV, + EFI_FLASH_AREA_MAIN_BIOS } + +}; + +#define NUM_FLASH_AREA_DATA (sizeof (mFlashAreaData) / sizeof (mFlashAreaData[0])) + +/** + Build GUID HOBs for platform specific flash map. + + @param FfsHeader Pointer this FFS file header. + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS Guid HOBs for platform flash map is built. + @retval Otherwise Failed to build the Guid HOB data. + +**/ +EFI_STATUS +PeimInitializeFlashMap ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + UINTN Index; + EFI_FLASH_AREA_HOB_DATA FlashHobData; + + // + // Build flash area entries as GUIDed HOBs. + // + for (Index = 0; Index < NUM_FLASH_AREA_DATA; Index++) { + ZeroMem(&FlashHobData, sizeof (EFI_FLASH_AREA_HOB_DATA)); + + FlashHobData.AreaType = mFlashAreaData[Index].AreaType; + FlashHobData.NumberOfEntries = 1; + FlashHobData.SubAreaData.Attributes = mFlashAreaData[Index].Attributes; + 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: + 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; + } + + PeiBuildHobGuidData(PeiServices, + &gEfiFlashMapHobGuid, + &FlashHobData, + sizeof (EFI_FLASH_AREA_HOB_DATA) + ); + } + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/LegacySpeaker.c b/Vlv2TbltDevicePkg/PlatformInitPei/LegacySpeaker.c new file mode 100644 index 0000000000..7ec276b089 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/LegacySpeaker.c @@ -0,0 +1,173 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + LegacySpeaker.c + +Abstract: + + This file implements PEIM for Legacy Speaker. This file is valid for platforms both + on IA32 and Itanium Product Family + +--*/ + +#include "PlatformEarlyInit.h" + +EFI_STATUS +OutputBeep ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN NumberOfBeep, + IN UINTN BeepDuration, + IN UINTN TimerInterval + ); + +/** + This function will enable the speaker to generate beep + + @param PeiServices PeiServices to locate PPI + + @retval EFI_STATUS + +**/ +EFI_STATUS +TurnOnSpeaker ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + UINT8 Data; + Data = IoRead8 (EFI_SPEAKER_CONTROL_PORT); + Data |= 0x03; + IoWrite8(EFI_SPEAKER_CONTROL_PORT, Data); + return EFI_SUCCESS; +} + +/** + This function will stop beep from speaker. + + @param PeiServices PeiServices to locate PPI + + @retval Status + +**/ +EFI_STATUS +TurnOffSpeaker ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + UINT8 Data; + + Data = IoRead8 (EFI_SPEAKER_CONTROL_PORT); + Data &= 0xFC; + IoWrite8(EFI_SPEAKER_CONTROL_PORT, Data); + return EFI_SUCCESS; +} + + +EFI_STATUS +OutputBeep ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN NumberOfBeep, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ) +{ + UINTN Num; + EFI_PEI_STALL_PPI* StallPpi; + + (**PeiServices).LocatePpi (PeiServices, &gEfiPeiStallPpiGuid, 0, NULL, (void **)&StallPpi); + + for (Num=0; Num < NumberOfBeep; Num++) { + TurnOnSpeaker (PeiServices); + StallPpi->Stall(PeiServices, StallPpi, BeepDuration); + TurnOffSpeaker(PeiServices); + StallPpi->Stall(PeiServices, StallPpi, TimeInterval); + } + + return EFI_SUCCESS; +} + +/** + This function will program the speaker tone frequency. The value should be with 64k + boundary since it takes only 16 bit value which gets programmed in two step IO opearattion + + Frequency - A value which should be 16 bit only. + + EFI_SUCESS + +**/ +EFI_STATUS +EFIAPI +ProgramToneFrequency ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Frequency + ) +{ + UINT8 Data; + + Data = 0xB6; + IoWrite8(EFI_TIMER_CONTROL_PORT, Data); + + Data = (UINT8)(Frequency & 0x00FF); + IoWrite8(EFI_TIMER_2_PORT, Data); + Data = (UINT8)((Frequency & 0xFF00) >> 8); + IoWrite8(EFI_TIMER_2_PORT, Data); + return EFI_SUCCESS; +} + +/** + This function will generate the beep for specified duration. + + @param PeiServices PeiServices to locate various PPIs + @param NumberOfBeeps Number of beeps which user want to produce + @param BeepDuration Duration for speaker gate need to be enabled + @param TimeInterval Interval between each beep + + @retval EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +GenerateBeepTone ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN NumberOfBeeps, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ) +{ + + if ((NumberOfBeeps == 1) && (BeepDuration == 0) && (TimeInterval == 0)) { + TurnOnSpeaker (PeiServices); + return EFI_SUCCESS; + } + + if ((NumberOfBeeps == 0) && (BeepDuration == 0) && (TimeInterval == 0)) { + TurnOffSpeaker (PeiServices); + return EFI_SUCCESS; + } + + if (BeepDuration == 0) { + BeepDuration = EFI_DEFAULT_SHORT_BEEP_DURATION; + } + + if (TimeInterval == 0) { + TimeInterval = EFI_DEFAULT_BEEP_TIME_INTERVAL; + } + + OutputBeep (PeiServices, NumberOfBeeps, BeepDuration, TimeInterval); + return EFI_SUCCESS; + + +} + diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/LegacySpeaker.h b/Vlv2TbltDevicePkg/PlatformInitPei/LegacySpeaker.h new file mode 100644 index 0000000000..7f806a7a29 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/LegacySpeaker.h @@ -0,0 +1,76 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + LegacySpeaker.h + +Abstract: + + Speaker enabling related data + +--*/ + +#ifndef _PEI_LEGACY_SPEAKER_H +#define _PEI_LEGACY_SPEAKER_H + + +// +// Speaker Related Port Information +// +#define EFI_TIMER_COUNTER_PORT 0x40 +#define EFI_TIMER_CONTROL_PORT 0x43 +#define EFI_TIMER_2_PORT 0x42 +#define EFI_SPEAKER_CONTROL_PORT 0x61 + +#define EFI_SPEAKER_OFF_MASK 0xFC + +#define EFI_DEFAULT_BEEP_FREQUENCY 0x500 + +// +// Default Intervals/Beep Duration +// +#define EFI_DEFAULT_LONG_BEEP_DURATION 0x70000 +#define EFI_DEFAULT_SHORT_BEEP_DURATION 0x50000 +#define EFI_DEFAULT_BEEP_TIME_INTERVAL 0x20000 + + +EFI_STATUS +EFIAPI +ProgramToneFrequency ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Frequency + ); + + +EFI_STATUS +EFIAPI +GenerateBeepTone ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN NumberOfBeeps, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ); + +EFI_STATUS +TurnOnSpeaker ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +TurnOffSpeaker ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +#endif diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/MchInit.c b/Vlv2TbltDevicePkg/PlatformInitPei/MchInit.c new file mode 100644 index 0000000000..4cad67c541 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/MchInit.c @@ -0,0 +1,77 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + MchInit.c + +Abstract: + + +--*/ + + +#include "PlatformEarlyInit.h" + +#define PSE_PAGE_SIZE 0x400000 // 4MB + +extern BOOLEAN ImageInMemory; + + +VOID +EfiCommonLibEnablePsePaging ( + IN UINT32 PDBR + ); + +VOID +EfiCommonLibDisablePsePaging ( + ); + +/** + + Initialize the MCH Thermal Sensor + +**/ +VOID +InitMchThermalSensor() +{ +} + +/** + + Programs and enables the CRID for MCH and ICH + +**/ +VOID +ProgramMchCRID( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ +} + +/** + + Initialize the GPIO IO selection, GPIO USE selection, and GPIO signal inversion registers + +**/ +VOID +MchInit ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + + return; +} + + diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/MemoryCallback.c b/Vlv2TbltDevicePkg/PlatformInitPei/MemoryCallback.c new file mode 100644 index 0000000000..31cc88a576 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/MemoryCallback.c @@ -0,0 +1,345 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + MemoryCallback.c + +Abstract: + + EFI 2.0 PEIM to provide the platform support functionality on the Bridgeport. + +--*/ + +#include "PlatformEarlyInit.h" + + +VOID +UpdateDefaultSetupValue ( + IN EFI_PLATFORM_INFO_HOB *PlatformInfo + ) +{ +return; +} + +/** + PEI termination callback. + + @param PeiServices General purpose services available to every PEIM. + @param NotifyDescriptor Not uesed. + @param Ppi Not uesed. + + @retval EFI_SUCCESS If the interface could be successfully + installed. + +**/ +EFI_STATUS +EFIAPI +EndOfPeiPpiNotifyCallback ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + UINT64 MemoryTop; + UINT64 LowUncableBase; + EFI_PLATFORM_INFO_HOB *PlatformInfo; + UINT32 HecBaseHigh; + EFI_BOOT_MODE BootMode; + EFI_PEI_HOB_POINTERS Hob; + + Status = (*PeiServices)->GetBootMode( + PeiServices, + &BootMode + ); + + ASSERT_EFI_ERROR (Status); + + // + // Set the some PCI and chipset range as UC + // And align to 1M at leaset + // + Hob.Raw = GetFirstGuidHob (&gEfiPlatformInfoGuid); + ASSERT (Hob.Raw != NULL); + PlatformInfo = GET_GUID_HOB_DATA(Hob.Raw); + + UpdateDefaultSetupValue (PlatformInfo); + + DEBUG ((EFI_D_ERROR, "Memory TOLM: %X\n", PlatformInfo->MemData.MemTolm)); + DEBUG ((EFI_D_ERROR, "PCIE OSBASE: %lX\n", PlatformInfo->PciData.PciExpressBase)); + DEBUG ( + (EFI_D_ERROR, + "PCIE BASE: %lX Size : %X\n", + PlatformInfo->PciData.PciExpressBase, + PlatformInfo->PciData.PciExpressSize) + ); + DEBUG ( + (EFI_D_ERROR, + "PCI32 BASE: %X Limit: %X\n", + PlatformInfo->PciData.PciResourceMem32Base, + PlatformInfo->PciData.PciResourceMem32Limit) + ); + DEBUG ( + (EFI_D_ERROR, + "PCI64 BASE: %lX Limit: %lX\n", + PlatformInfo->PciData.PciResourceMem64Base, + PlatformInfo->PciData.PciResourceMem64Limit) + ); + DEBUG ((EFI_D_ERROR, "UC START: %lX End : %lX\n", PlatformInfo->MemData.MemMir0, PlatformInfo->MemData.MemMir1)); + + LowUncableBase = PlatformInfo->MemData.MemMaxTolm; + LowUncableBase &= (0x0FFF00000); + MemoryTop = (0x100000000); + + if (BootMode != BOOT_ON_S3_RESUME) { + // + // In BIOS, HECBASE will be always below 4GB + // + HecBaseHigh = (UINT32) RShiftU64 (PlatformInfo->PciData.PciExpressBase, 28); + ASSERT (HecBaseHigh < 16); + } + + return Status; +} + +/** + Install Firmware Volume Hob's once there is main memory + + @param PeiServices General purpose services available to every PEIM. + @param NotifyDescriptor Notify that this module published. + @param Ppi PPI that was installed. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +EFIAPI +MemoryDiscoveredPpiNotifyCallback ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + EFI_CPUID_REGISTER FeatureInfo; + UINT8 CpuAddressWidth; + UINT16 Pm1Cnt; + EFI_PEI_HOB_POINTERS Hob; + EFI_PLATFORM_INFO_HOB *PlatformInfo; + UINT32 RootComplexBar; + UINT32 PmcBase; + UINT32 IoBase; + UINT32 IlbBase; + UINT32 SpiBase; + UINT32 MphyBase; + + // + // Get Platform Info HOB + // + Hob.Raw = GetFirstGuidHob (&gEfiPlatformInfoGuid); + ASSERT (Hob.Raw != NULL); + PlatformInfo = GET_GUID_HOB_DATA(Hob.Raw); + + Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode); + + // + // Check if user wants to turn off in PEI phase + // + if ((BootMode != BOOT_ON_S3_RESUME) && (BootMode != BOOT_ON_FLASH_UPDATE)) { + CheckPowerOffNow(); + } else { + Pm1Cnt = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT); + Pm1Cnt &= ~B_PCH_ACPI_PM1_CNT_SLP_TYP; + IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, Pm1Cnt); + } + + #ifndef MINNOW2_FSP_BUILD + // + // Set PEI cache mode here + // + SetPeiCacheMode (PeiServices); + #endif + + // + // Pulish memory tyoe info + // + PublishMemoryTypeInfo (); + + // + // Work done if on a S3 resume + // + if (BootMode == BOOT_ON_S3_RESUME) { + // + //Program the side band packet register to send a sideband message to Punit + //To indicate that DRAM has been initialized and PUNIT FW base address in memory. + // + return EFI_SUCCESS; + } + + RootComplexBar = MmPci32( 0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_RCBA ) & B_PCH_LPC_RCBA_BAR; + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + RootComplexBar, + 0x1000 + ); + DEBUG ((EFI_D_INFO, "RootComplexBar : 0x%x\n", RootComplexBar)); + + PmcBase = MmPci32( 0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_PMC_BASE ) & B_PCH_LPC_PMC_BASE_BAR; + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + PmcBase, + 0x1000 + ); + DEBUG ((EFI_D_INFO, "PmcBase : 0x%x\n", PmcBase)); + + IoBase = MmPci32( 0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_IO_BASE ) & B_PCH_LPC_IO_BASE_BAR; + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + IoBase, + 0x4000 + ); + DEBUG ((EFI_D_INFO, "IoBase : 0x%x\n", IoBase)); + + IlbBase = MmPci32( 0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_ILB_BASE ) & B_PCH_LPC_ILB_BASE_BAR; + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + IlbBase, + 0x1000 + ); + DEBUG ((EFI_D_INFO, "IlbBase : 0x%x\n", IlbBase)); + + SpiBase = MmPci32( 0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_SPI_BASE ) & B_PCH_LPC_SPI_BASE_BAR; + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + SpiBase, + 0x1000 + ); + DEBUG ((EFI_D_INFO, "SpiBase : 0x%x\n", SpiBase)); + + MphyBase = MmPci32( 0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_MPHY_BASE ) & B_PCH_LPC_MPHY_BASE_BAR; + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + MphyBase, + 0x100000 + ); + DEBUG ((EFI_D_INFO, "MphyBase : 0x%x\n", MphyBase)); + + // + // Local APIC + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + LOCAL_APIC_ADDRESS, + 0x1000 + ); + DEBUG ((EFI_D_INFO, "LOCAL_APIC_ADDRESS : 0x%x\n", LOCAL_APIC_ADDRESS)); + + // + // IO APIC + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + IO_APIC_ADDRESS, + 0x1000 + ); + DEBUG ((EFI_D_INFO, "IO_APIC_ADDRESS : 0x%x\n", IO_APIC_ADDRESS)); + + // + // Adding the PCIE Express area to the E820 memory table as type 2 memory. + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + PlatformInfo->PciData.PciExpressBase, + PlatformInfo->PciData.PciExpressSize + ); + DEBUG ((EFI_D_INFO, "PciExpressBase : 0x%x\n", PlatformInfo->PciData.PciExpressBase)); + + // + // Adding the Flashpart to the E820 memory table as type 2 memory. + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_FIRMWARE_DEVICE, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + FixedPcdGet32 (PcdFlashAreaBaseAddress), + FixedPcdGet32 (PcdFlashAreaSize) + ); + DEBUG ((EFI_D_INFO, "FLASH_BASE_ADDRESS : 0x%x\n", FixedPcdGet32 (PcdFlashAreaBaseAddress))); + + // + // Create a CPU hand-off information + // + CpuAddressWidth = 32; + AsmCpuid (EFI_CPUID_EXTENDED_FUNCTION, &FeatureInfo.RegEax, &FeatureInfo.RegEbx, &FeatureInfo.RegEcx, &FeatureInfo.RegEdx); + if (FeatureInfo.RegEax >= EFI_CPUID_VIRT_PHYS_ADDRESS_SIZE) { + AsmCpuid (EFI_CPUID_VIRT_PHYS_ADDRESS_SIZE, &FeatureInfo.RegEax, &FeatureInfo.RegEbx, &FeatureInfo.RegEcx, &FeatureInfo.RegEdx); + CpuAddressWidth = (UINT8) (FeatureInfo.RegEax & 0xFF); + } + + BuildCpuHob(CpuAddressWidth, 16); + ASSERT_EFI_ERROR (Status); + + return Status; + +} + + +EFI_STATUS +ValidateFvHeader ( + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ) +{ + 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 + // + 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 = *Ptr++; + HeaderLength--; + } + + if (Checksum != 0) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/MemoryPeim.c b/Vlv2TbltDevicePkg/PlatformInitPei/MemoryPeim.c new file mode 100644 index 0000000000..9592b07705 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/MemoryPeim.c @@ -0,0 +1,369 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + MemoryPeim.c + +Abstract: + + Tiano PEIM to provide the platform support functionality. + This file implements the Platform Memory Range PPI + +--*/ + +#include "PlatformEarlyInit.h" + +// +// Need min. of 48MB PEI phase +// +#define PEI_MIN_MEMORY_SIZE (6 * 0x800000) +#define PEI_RECOVERY_MIN_MEMORY_SIZE (6 * 0x800000) + +// +// This is the memory needed for PEI to start up DXE. +// +// Over-estimating this size will lead to higher fragmentation +// of main memory. Under-estimation of this will cause catastrophic +// failure of PEI to load DXE. Generally, the failure may only be +// realized during capsule updates. +// +#define PRERESERVED_PEI_MEMORY ( \ + EFI_SIZE_TO_PAGES (3 * 0x800000) /* PEI Core memory based stack */ \ + ) + +EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = { + { EfiACPIReclaimMemory, 0x40 }, // 0x40 pages = 256k for ASL + { EfiACPIMemoryNVS, 0x100 }, // 0x100 pages = 1 MB for S3, SMM, HII, etc + { EfiReservedMemoryType, 0x600 }, // 48k for BIOS Reserved + { EfiMemoryMappedIO, 0 }, + { EfiMemoryMappedIOPortSpace, 0 }, + { EfiPalCode, 0 }, + { EfiRuntimeServicesCode, 0x200 }, + { EfiRuntimeServicesData, 0x100 }, + { EfiLoaderCode, 0x100 }, + { EfiLoaderData, 0x100 }, + { EfiBootServicesCode, 0x800 }, + { EfiBootServicesData, 0x2500}, + { EfiConventionalMemory, 0 }, + { EfiUnusableMemory, 0 }, + { EfiMaxMemoryType, 0 } +}; + +STATIC +EFI_STATUS +GetMemorySize ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT64 *LowMemoryLength, + OUT UINT64 *HighMemoryLength + ); + + + +EFI_STATUS +EFIAPI +SetPeiCacheMode ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + PEI_CACHE_PPI *CachePpi; + + EFI_BOOT_MODE BootMode; + UINT64 MemoryLength; + UINT64 MemOverflow; + UINT64 MemoryLengthUc; + UINT64 MaxMemoryLength; + UINT64 LowMemoryLength; + UINT64 HighMemoryLength; + UINT8 Index; + MTRR_SETTINGS MtrrSetting; + + // + // Load Cache PPI + // + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPeiCachePpiGuid, // GUID + 0, // Instance + NULL, // EFI_PEI_PPI_DESCRIPTOR + (void **)&CachePpi // PPI + ); + if (!EFI_ERROR(Status)) { + // + // Clear the CAR Settings (Default Cache Type => UC) + // + DEBUG ((EFI_D_INFO, "Reset cache attribute and disable CAR. \n")); + CachePpi->ResetCache( + (EFI_PEI_SERVICES**)PeiServices, + CachePpi + ); + } + + + // + // Variable initialization + // + LowMemoryLength = 0; + HighMemoryLength = 0; + MemoryLengthUc = 0; + + Status = (*PeiServices)->GetBootMode ( + PeiServices, + &BootMode + ); + + // + // Determine memory usage + // + GetMemorySize ( + PeiServices, + &LowMemoryLength, + &HighMemoryLength + ); + + LowMemoryLength = (EFI_PHYSICAL_ADDRESS)MmPci32( 0, 0, 2, 0, 0x70); + LowMemoryLength &= 0xFFF00000ULL; + + MaxMemoryLength = LowMemoryLength; + + // + // Round up to nearest 256MB with high memory and 64MB w/o high memory + // + if (HighMemoryLength != 0 ) { + MemOverflow = (LowMemoryLength & 0x0fffffff); + if (MemOverflow != 0) { + MaxMemoryLength = LowMemoryLength + (0x10000000 - MemOverflow); + } + } else { + MemOverflow = (LowMemoryLength & 0x03ffffff); + if (MemOverflow != 0) { + MaxMemoryLength = LowMemoryLength + (0x4000000 - MemOverflow); + } + } + + ZeroMem (&MtrrSetting, sizeof(MTRR_SETTINGS)); + for (Index = 0; Index < 2; Index++) { + MtrrSetting.Fixed.Mtrr[Index]=0x0606060606060606; + } + for (Index = 2; Index < 11; Index++) { + MtrrSetting.Fixed.Mtrr[Index]=0x0505050505050505; + } + + // + // Cache the flash area to improve the boot performance in PEI phase + // + Index = 0; + MtrrSetting.Variables.Mtrr[0].Base = (FixedPcdGet32 (PcdFlashAreaBaseAddress) | CacheWriteProtected); + MtrrSetting.Variables.Mtrr[0].Mask = ((~((UINT64)(FixedPcdGet32 (PcdFlashAreaSize) - 1))) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED; + Index ++; + + MemOverflow =0; + while (MaxMemoryLength > MemOverflow){ + MtrrSetting.Variables.Mtrr[Index].Base = (MemOverflow & MTRR_LIB_CACHE_VALID_ADDRESS) | CacheWriteBack; + MemoryLength = MaxMemoryLength - MemOverflow; + MemoryLength = GetPowerOfTwo64 (MemoryLength); + MtrrSetting.Variables.Mtrr[Index].Mask = ((~(MemoryLength - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED; + + MemOverflow += MemoryLength; + Index++; + } + + MemoryLength = LowMemoryLength; + + while (MaxMemoryLength != MemoryLength) { + MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength); + + 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++; + } + + MemOverflow =0x100000000; + while (HighMemoryLength > 0) { + MtrrSetting.Variables.Mtrr[Index].Base = (MemOverflow & MTRR_LIB_CACHE_VALID_ADDRESS) | CacheWriteBack; + MemoryLength = HighMemoryLength; + MemoryLength = GetPowerOfTwo64 (MemoryLength); + + if (MemoryLength > MemOverflow){ + MemoryLength = MemOverflow; + } + + MtrrSetting.Variables.Mtrr[Index].Mask = ((~(MemoryLength - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED; + + MemOverflow += MemoryLength; + HighMemoryLength -= MemoryLength; + Index++; + } + + + for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) { + if (MtrrSetting.Variables.Mtrr[Index].Base == 0){ + break; + } + DEBUG ((EFI_D_INFO, "Base=%lx, Mask=%lx\n",MtrrSetting.Variables.Mtrr[Index].Base ,MtrrSetting.Variables.Mtrr[Index].Mask)); + } + + // + // set FE/E bits for IA32_MTRR_DEF_TYPE + // + MtrrSetting.MtrrDefType |= 3 <<10; + + MtrrSetAllMtrrs(&MtrrSetting); + + + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SetDxeCacheMode ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + // + // This is not needed for now. + // + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GetMemorySize ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT64 *LowMemoryLength, + OUT UINT64 *HighMemoryLength + ) +{ + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS Hob; + + *HighMemoryLength = 0; + *LowMemoryLength = 0x100000; + + // + // Get the HOB list for processing + // + Status = (*PeiServices)->GetHobList (PeiServices, (void **)&Hob.Raw); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Collect memory ranges + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { + // + // Need memory above 1MB to be collected here + // + if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000 && + Hob.ResourceDescriptor->PhysicalStart < (EFI_PHYSICAL_ADDRESS) 0x100000000) { + *LowMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength); + } else if (Hob.ResourceDescriptor->PhysicalStart >= (EFI_PHYSICAL_ADDRESS) 0x100000000) { + *HighMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength); + } + } + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + + return EFI_SUCCESS; +} + + +/** + Publish Memory Type Information. + + @param NULL + + @retval EFI_SUCCESS Success. + @retval Others Errors have occurred. +**/ + +EFI_STATUS +EFIAPI +PublishMemoryTypeInfo ( + void + ) +{ + EFI_STATUS Status; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; + UINTN DataSize; + EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1]; + + Status = PeiServicesLocatePpi ( + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&Variable + ); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "WARNING: Locating Pei variable failed 0x%x \n", Status)); + DEBUG((EFI_D_ERROR, "Build Hob from default\n")); + // + // Build the default GUID'd HOB for DXE + // + BuildGuidDataHob ( + &gEfiMemoryTypeInformationGuid, + mDefaultMemoryTypeInformation, + sizeof (mDefaultMemoryTypeInformation) + ); + + return Status; + } + + + DataSize = sizeof (MemoryData); + + // + // This variable is saved in BDS stage. Now read it back + // + Status = Variable->GetVariable ( + Variable, + EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, + &gEfiMemoryTypeInformationGuid, + NULL, + &DataSize, + &MemoryData + ); + if (EFI_ERROR (Status)) { + // + //build default + // + DEBUG((EFI_D_ERROR, "Build Hob from default\n")); + BuildGuidDataHob ( + &gEfiMemoryTypeInformationGuid, + mDefaultMemoryTypeInformation, + sizeof (mDefaultMemoryTypeInformation) + ); + + } else { + // + // Build the GUID'd HOB for DXE from variable + // + DEBUG((EFI_D_ERROR, "Build Hob from variable \n")); + BuildGuidDataHob ( + &gEfiMemoryTypeInformationGuid, + MemoryData, + DataSize + ); + } + + return Status; +} + diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/PchInitPeim.c b/Vlv2TbltDevicePkg/PlatformInitPei/PchInitPeim.c new file mode 100644 index 0000000000..30f87c1906 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/PchInitPeim.c @@ -0,0 +1,813 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PchInitPeim.c + +Abstract: + + Do Early PCH platform initialization. + + +--*/ + +#include "PlatformEarlyInit.h" +#include "Ppi/PchPlatformPolicy.h" +#include "PchRegs.h" +#include +#include "Ppi/PchInit.h" +#include + +EFI_GUID gPchPlatformPolicyPpiGuid = PCH_PLATFORM_POLICY_PPI_GUID; + +#define MC_PMSTS_OFFSET 0xC + +#define DEFAULT_BUS_INFO 0x2020 + + +#define PCI_LPC_BASE (0x8000F800) +#define PCI_LPC_REG(x) (PCI_LPC_BASE + (x)) +#define PCIEX_BASE_ADDRESS 0xE0000000 +#define PciD31F0RegBase PCIEX_BASE_ADDRESS + (UINT32) (31 << 15) + +VOID +PchPolicySetupInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN SYSTEM_CONFIGURATION *SystemConfiguration + ); + +VOID +PchInitInterrupt ( + IN SYSTEM_CONFIGURATION *SystemConfiguration + ); + +#ifndef __GNUC__ +#pragma warning (push) +#pragma warning (disable : 4245) +#pragma warning (pop) +#endif + +UINT8 +ReadCmosBank1Byte ( + IN UINT8 Address + ) +{ + UINT8 Data; + + IoWrite8(R_PCH_RTC_EXT_INDEX, Address); + Data = IoRead8 (R_PCH_RTC_EXT_TARGET); + return Data; +} + +VOID +WriteCmosBank1Byte ( + IN UINT8 Address, + IN UINT8 Data + ) +{ + IoWrite8(R_PCH_RTC_EXT_INDEX, Address); + IoWrite8(R_PCH_RTC_EXT_TARGET, Data); +} + +/** + Turn off system if needed. + + @param PeiServices Pointer to PEI Services + @param CpuIo Pointer to CPU I/O Protocol + + @retval None. + +**/ +VOID +CheckPowerOffNow ( + VOID + ) +{ + UINT16 Pm1Sts; + + // + // Read and check the ACPI registers + // + Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS); + if ((Pm1Sts & B_PCH_ACPI_PM1_STS_PWRBTN) == B_PCH_ACPI_PM1_STS_PWRBTN) { + IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_PWRBTN); + IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, V_PCH_ACPI_PM1_CNT_S5); + IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, V_PCH_ACPI_PM1_CNT_S5 + B_PCH_ACPI_PM1_CNT_SLP_EN); + + // + // Should not return + // + CpuDeadLoop(); + } +} + +VOID +ClearPowerState ( + IN SYSTEM_CONFIGURATION *SystemConfiguration + ) +{ + UINT8 Data8; + UINT16 Data16; + UINT32 Data32; + + // + // Check for PowerState option for AC power loss and program the chipset + // + + // + // Clear PWROK (Set to Clear) + // + MmioOr32 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, B_PCH_PMC_GEN_PMCON_PWROK_FLR); + + // + // Clear Power Failure Bit (Set to Clear) + // + // TODO: Check if it is OK to clear here + // + + MmioOr32 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR); + + // + // Clear the GPE and PM enable + // + IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_EN, (UINT16) 0x00); + IoWrite32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_GPE0a_EN, (UINT32) 0x00); + + // + // Halt the TCO timer + // + Data16 = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_TCO_CNT); + Data16 |= B_PCH_TCO_CNT_TMR_HLT; + IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_TCO_CNT, Data16); + + // + // if NMI_NOW_STS is set + // NMI NOW bit is "Write '1' to clear" + // + Data8 = MmioRead8(ILB_BASE_ADDRESS + R_PCH_ILB_GNMI); + if ((Data8 & B_PCH_ILB_GNMI_NMINS) == B_PCH_ILB_GNMI_NMINS) { + MmioOr8 (ILB_BASE_ADDRESS + R_PCH_ILB_GNMI, B_PCH_ILB_GNMI_NMIN); + } + + // + // Before we clear the TO status bit here we need to save the results in a CMOS bit for later use. + // + Data32 = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_TCO_STS); + if ((Data32 & B_PCH_TCO_STS_SECOND_TO) == B_PCH_TCO_STS_SECOND_TO) + { +#if (defined(HW_WATCHDOG_TIMER_SUPPORT) && (HW_WATCHDOG_TIMER_SUPPORT != 0)) + WriteCmosBank1Byte ( + EFI_CMOS_PERFORMANCE_FLAGS, + ReadCmosBank1Byte (EFI_CMOS_PERFORMANCE_FLAGS) | B_CMOS_TCO_WDT_RESET + ); +#endif + } +} + +/*++ + + Clear any SMI status or wake status left over from boot. + +**/ +VOID +ClearSmiAndWake ( + VOID + ) +{ + UINT16 Pm1Sts; + UINT32 Gpe0Sts; + UINT32 SmiSts; + + // + // Read the ACPI registers + // + Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS); + Gpe0Sts = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_GPE0a_STS); + SmiSts = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_SMI_STS); + + // + // Register Wake up reason for S4. This information is used to notify + // WinXp of wake up reason because S4 wake up path doesn't keep SCI. + // This is important for Viiv(Quick resume) platform. + // + + // + // First Clear CMOS S4 Wake up flag. + // + WriteCmosBank1Byte(CMOS_S4_WAKEUP_FLAG_ADDRESS, 0); + + // + // Check wake up reason and set CMOS accordingly. Currently checks + // Power button, USB, PS/2. + // Note : PS/2 wake up is using GPI13 (IO_PME). This must be changed depending + // on board design. + // + if ((Pm1Sts & B_PCH_ACPI_PM1_STS_PWRBTN) || (Gpe0Sts & (B_PCH_ACPI_GPE0a_STS_CORE_GPIO | B_PCH_ACPI_GPE0a_STS_SUS_GPIO))) { + WriteCmosBank1Byte(CMOS_S4_WAKEUP_FLAG_ADDRESS, 1); + } + + // + // Clear any SMI or wake state from the boot + // + Pm1Sts = (B_PCH_ACPI_PM1_STS_PRBTNOR | B_PCH_ACPI_PM1_STS_PWRBTN); + + Gpe0Sts |= + ( + B_PCH_ACPI_GPE0a_STS_CORE_GPIO | + B_PCH_ACPI_GPE0a_STS_SUS_GPIO | + B_PCH_ACPI_GPE0a_STS_PME_B0 | + B_PCH_ACPI_GPE0a_STS_BATLOW | + B_PCH_ACPI_GPE0a_STS_PCI_EXP | + B_PCH_ACPI_GPE0a_STS_GUNIT_SCI | + B_PCH_ACPI_GPE0a_STS_PUNIT_SCI | + B_PCH_ACPI_GPE0a_STS_SWGPE | + B_PCH_ACPI_GPE0a_STS_HOT_PLUG + ); + + SmiSts |= + ( + B_PCH_SMI_STS_SMBUS | + B_PCH_SMI_STS_PERIODIC | + B_PCH_SMI_STS_TCO | + B_PCH_SMI_STS_SWSMI_TMR | + B_PCH_SMI_STS_APM | + B_PCH_SMI_STS_ON_SLP_EN | + B_PCH_SMI_STS_BIOS + ); + + // + // Write them back + // + IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS, Pm1Sts); + IoWrite32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_GPE0a_STS, Gpe0Sts); + IoWrite32 (ACPI_BASE_ADDRESS + R_PCH_SMI_STS, SmiSts); +} + +/** + Issue PCI-E Secondary Bus Reset + + @param Bus Bus number of the bridge + @param Dev Devices number of the bridge + @param Fun Function number of the bridge + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +PcieSecondaryBusReset ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT8 Bus, + IN UINT8 Dev, + IN UINT8 Fun + ) +{ + EFI_PEI_STALL_PPI *PeiStall; + EFI_STATUS Status; + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiPeiStallPpiGuid, + 0, + NULL, + (void **)&PeiStall + ); + ASSERT_EFI_ERROR (Status); + + // + // Issue secondary bus reset + // + MmPci16Or(0, Bus, Dev, Fun, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS); + + // + // Wait 1ms + // + PeiStall->Stall (PeiServices, PeiStall, 1000); + + + // + // Clear the reset bit + // Note: The PCIe spec suggests 100ms delay between clearing this bit and accessing + // the device's config space. Since we will not access the config space until we enter DXE + // we don't put delay expressly here. + // + MmPci16And(0, Bus, Dev, Fun, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, ~(EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS)); + + return EFI_SUCCESS; +} + +/** + Provide hard reset PPI service. + To generate full hard reset, write 0x0E to ICH RESET_GENERATOR_PORT (0xCF9). + + @param PeiServices General purpose services available to every PEIM. + + @retval Not return System reset occured. + @retval EFI_DEVICE_ERROR Device error, could not reset the system. + +**/ +EFI_STATUS +EFIAPI +IchReset ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + IoWrite8 ( + R_PCH_RST_CNT, + V_PCH_RST_CNT_HARDSTARTSTATE + ); + + IoWrite8 ( + R_PCH_RST_CNT, + V_PCH_RST_CNT_HARDRESET + ); + + // + // System reset occured, should never reach at this line. + // + ASSERT_EFI_ERROR (EFI_DEVICE_ERROR); + CpuDeadLoop(); + + return EFI_DEVICE_ERROR; +} + +VOID +PchPlatformLpcInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN SYSTEM_CONFIGURATION *SystemConfiguration + ) +{ + EFI_BOOT_MODE BootMode; + UINT8 Data8; + UINT16 Data16; + + (*PeiServices)->GetBootMode(PeiServices, &BootMode); + + if ((BootMode != BOOT_ON_S3_RESUME)) { + + // + // Clear all pending SMI. On S3 clear power button enable so it wll not generate an SMI + // + ClearSmiAndWake (); + } + + ClearPowerState (SystemConfiguration); + + // + // Need to set and clear SET bit (RTC_REGB Bit 7) as requested by the ICH EDS + // early in POST after each power up directly after coin-cell battery insertion. + // This is to avoid the UIP bit (RTC_REGA Bit 7) from stuck at "1". + // The UIP bit status may be polled by software (i.e ME FW) during POST. + // + if (MmioRead8 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1) & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) { + // + // Set and clear SET bit in RTC_REGB + // + IoWrite8(R_PCH_RTC_INDEX, R_PCH_RTC_REGISTERB); + Data8 = IoRead8(R_PCH_RTC_TARGET); + Data8 |= B_PCH_RTC_REGISTERB_SET; + IoWrite8(R_PCH_RTC_TARGET, Data8); + + IoWrite8(R_PCH_RTC_INDEX, R_PCH_RTC_REGISTERB); + Data8 &= (~B_PCH_RTC_REGISTERB_SET); + IoWrite8(R_PCH_RTC_TARGET, Data8); + + // + // Clear the UIP bit in RTC_REGA + // + IoWrite8(R_PCH_RTC_INDEX, R_PCH_RTC_REGISTERA); + IoWrite8(R_PCH_RTC_TARGET, 0x00); + } + + // + // Disable SERR NMI and IOCHK# NMI in port 61 + // + Data8 = IoRead8 (R_PCH_NMI_SC); + IoWrite8(R_PCH_NMI_SC, (UINT8) (Data8 | B_PCH_NMI_SC_PCI_SERR_EN | B_PCH_NMI_SC_IOCHK_NMI_EN)); + + // + // Enable Bus Master, I/O, Mem, and SERR on LPC bridge + // + Data16 = PchLpcPciCfg16 (R_PCH_LPC_COMMAND); + MmioWrite16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_COMMAND + ), + (Data16 | + B_PCH_LPC_COMMAND_IOSE | + B_PCH_LPC_COMMAND_MSE | + B_PCH_LPC_COMMAND_BME | + B_PCH_LPC_COMMAND_SERR_EN) + ); + + // + // Set Stretch S4 to 1-2s per marketing request. + // Note: This register is powered by RTC well. + // + MmioAndThenOr8 ( + PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1 , + (UINT8) (~B_PCH_PMC_GEN_PMCON_SLP_S4_MAW), + (UINT8) (B_PCH_PMC_GEN_PMCON_SLP_S4_ASE | V_PCH_PMC_GEN_PMCON_SLP_S4_MAW_4S) + ); + +} + +#define V_PCH_ILB_IRQE_UARTIRQEN_IRQ3 BIT3 // UART IRQ3 Enable + +VOID +UARTInit ( + IN SYSTEM_CONFIGURATION *SystemConfiguration + ) +{ + if (0) { // for fix cr4 issue + // + // Program and enable PMC Base. + // + IoWrite32 (0xCF8, PCI_LPC_REG(R_PCH_LPC_PMC_BASE)); + IoWrite32 (0xCFC, (PMC_BASE_ADDRESS | B_PCH_LPC_PMC_BASE_EN)); + + if( (SystemConfiguration->PcuUart1 == 1) && + (SystemConfiguration->LpssHsuart0Enabled == 0)){ + // + // Enable COM1 for debug message output. + // + MmioOr32 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, BIT24); + + // + //Enable internal UART3 port(COM1) + // + MmioOr8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) V_PCH_ILB_IRQE_UARTIRQEN_IRQ3); + MmioOr32 (IO_BASE_ADDRESS + 0x0520, 0x01); // UART3_RXD-L + MmioOr32 (IO_BASE_ADDRESS + 0x0530, 0x01); // UART3_TXD-0 + MmioOr8 (PciD31F0RegBase + R_PCH_LPC_UART_CTRL, (UINT8) B_PCH_LPC_UART_CTRL_COM1_EN); + } else { + // + //Disable UART3(COM1) + // + MmioAnd8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) ~V_PCH_ILB_IRQE_UARTIRQEN_IRQ3); + MmioAnd32 (IO_BASE_ADDRESS + 0x0520, ~(UINT32)0x07); + MmioAnd32 (IO_BASE_ADDRESS + 0x0530, ~(UINT32)0x07); + MmioAnd8 (PciD31F0RegBase + R_PCH_LPC_UART_CTRL, (UINT8) ~B_PCH_LPC_UART_CTRL_COM1_EN); + + + if (SystemConfiguration->LpssHsuart0Enabled == 1){ + // + //Valleyview BIOS Specification Vol2,17.2 + //LPSS_UART1 ¨C set each pad PAD_CONF0.Func_Pin_Mux to function 1: + // + MmioAnd8 (IO_BASE_ADDRESS + 0x0090, (UINT8)~0x07); + MmioOr8 (IO_BASE_ADDRESS + 0x0090, 0x01); + MmioAnd8 (IO_BASE_ADDRESS + 0x00D0, (UINT8)~0x07); + MmioOr8 (IO_BASE_ADDRESS + 0x00D0, 0x01); + + } + } + + + DEBUG ((EFI_D_ERROR, "EnableInternalUart\n")); + } else { + // + // If SIO UART interface selected + //Disable internal UART port(COM1) + // + if (0) {; // For fix CR4 issue + MmioAnd8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) ~V_PCH_ILB_IRQE_UARTIRQEN_IRQ3); + MmioAnd8 (IO_BASE_ADDRESS + 0x0090, (UINT8)~0x07); + MmioAnd8 (IO_BASE_ADDRESS + 0x00D0, (UINT8)~0x07); + MmioAnd8 (PciD31F0RegBase + R_PCH_LPC_UART_CTRL, (UINT8) ~B_PCH_LPC_UART_CTRL_COM1_EN); + + } + } +} + +VOID +IchRcrbInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN SYSTEM_CONFIGURATION *SystemConfiguration + ) +{ + UINT8 LpcRevisionID; + EFI_PLATFORM_CPU_INFO *PlatformCpuInfo; + EFI_PEI_HOB_POINTERS Hob; + EFI_BOOT_MODE BootMode; + + // + // Get Platform Info HOB + // + Hob.Raw = GetFirstGuidHob (&gEfiPlatformCpuInfoGuid); + ASSERT (Hob.Raw != NULL); + PlatformCpuInfo = GET_GUID_HOB_DATA(Hob.Raw); + + (*PeiServices)->GetBootMode(PeiServices, &BootMode); + + // + // If not recovery or flash update boot path. set the BIOS interface lock down bit. + // It locks the top swap bit and BIOS boot strap bits from being changed. + // + if ((BootMode != BOOT_IN_RECOVERY_MODE) && (BootMode != BOOT_ON_FLASH_UPDATE)) { + MmioOr8 (RCBA_BASE_ADDRESS + R_PCH_RCRB_GCS, B_PCH_RCRB_GCS_BILD); + } + + // + // Disable the Watchdog timer expiration from causing a system reset + // + MmioOr8 (PMC_BASE_ADDRESS + R_PCH_PMC_PM_CFG, B_PCH_PMC_PM_CFG_NO_REBOOT); + + // + // Initial RCBA according to the PeiRCBA table + // + LpcRevisionID = PchLpcPciCfg8 (R_PCH_LPC_RID_CC); + + if ((BootMode == BOOT_ON_S3_RESUME)) { + // + // We are resuming from S3 + // Enable HPET if enabled in Setup + // ICH Config register Offset 0x3404 bit 7 (Enable) = 1, + // Bit 1:0 (Mem I/O address) = 0 (0xFED00000) + // + MmioOr8 (R_PCH_PCH_HPET + R_PCH_PCH_HPET_GCFG, B_PCH_PCH_HPET_GCFG_EN); + + } + +} + + +EFI_STATUS +PlatformPchInit ( + IN SYSTEM_CONFIGURATION *SystemConfiguration, + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 PlatformType + ) +{ + IchRcrbInit (PeiServices, SystemConfiguration); + + // + // PCH Policy Initialization based on Setup variable. + // + PchPolicySetupInit (PeiServices, SystemConfiguration); + + UARTInit(SystemConfiguration); + + PchPlatformLpcInit (PeiServices, SystemConfiguration); + + return EFI_SUCCESS; +} + +/** + + Returns the state of A16 inversion + + @retval TRUE A16 is inverted + @retval FALSE A16 is not inverted + +**/ +BOOLEAN +IsA16Inverted ( + ) +{ + UINT8 Data; + Data = MmioRead8 (RCBA_BASE_ADDRESS + R_PCH_RCRB_GCS); + return (Data & B_PCH_RCRB_GCS_TS) ? TRUE : FALSE; +} + +VOID +PchPolicySetupInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN SYSTEM_CONFIGURATION *SystemConfiguration + ) +{ + EFI_STATUS Status; + EFI_PEI_PPI_DESCRIPTOR *PchPlatformPolicyPpiDesc; + PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi; + PCH_HPET_CONFIG *HpetConfig; + PCH_PCIE_CONFIG *PcieConfig; + UINT8 Index; + PCH_IOAPIC_CONFIG *IoApicConfig; + PCH_LPSS_CONFIG *LpssConfig; + UINT32 SpiHsfsReg; + UINT32 SpiFdodReg; + +// +// Disable codec ALC-262 +// + UINT32 IoBase; + + // + // Install Pch Platform Policy PPI. As we depend on Pch Init PPI so we are executed after + // PchInit PEIM. Thus we can insure PCH Initialization is performed when we install the Pch Platform Policy PPI, + // as PchInit PEIM registered a notification function on our policy PPI. + // + // --cr-- For better code structure / modularity, we should use a notification function on Pch Init PPI to perform + // actions that depend on PchInit PEIM's initialization. + // + //Todo: confirm if we need update to PCH_PLATFORM_POLICY_PPI_REVISION_5 + // + DEBUG ((EFI_D_ERROR, "PchPolicySetupInit() - Start\n")); + + Status = (*PeiServices)->AllocatePool (PeiServices, sizeof (EFI_PEI_PPI_DESCRIPTOR), (void **)&PchPlatformPolicyPpiDesc); + ASSERT_EFI_ERROR (Status); + + Status = (*PeiServices)->AllocatePool (PeiServices, sizeof (PCH_PLATFORM_POLICY_PPI), (void **)&PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + + Status = (*PeiServices)->AllocatePool (PeiServices, sizeof (PCH_HPET_CONFIG), (void **)&HpetConfig); + ASSERT_EFI_ERROR (Status); + + Status = (*PeiServices)->AllocatePool (PeiServices, sizeof (PCH_PCIE_CONFIG), (void **)&PcieConfig); + ASSERT_EFI_ERROR (Status); + + Status = (*PeiServices)->AllocatePool (PeiServices, sizeof (PCH_IOAPIC_CONFIG), (void **)&IoApicConfig); + ASSERT_EFI_ERROR (Status); + + Status = (*PeiServices)->AllocatePool (PeiServices, sizeof (PCH_LPSS_CONFIG), (void **)&LpssConfig); + ASSERT_EFI_ERROR (Status); + + PchPlatformPolicyPpi->Revision = PCH_PLATFORM_POLICY_PPI_REVISION_1; + PchPlatformPolicyPpi->BusNumber = DEFAULT_PCI_BUS_NUMBER_PCH; + PchPlatformPolicyPpi->SpiBase = SPI_BASE_ADDRESS; + PchPlatformPolicyPpi->PmcBase = PMC_BASE_ADDRESS; + PchPlatformPolicyPpi->IoBase = IO_BASE_ADDRESS; + PchPlatformPolicyPpi->IlbBase = ILB_BASE_ADDRESS; + PchPlatformPolicyPpi->PUnitBase = PUNIT_BASE_ADDRESS; + PchPlatformPolicyPpi->MphyBase = MPHY_BASE_ADDRESS; + PchPlatformPolicyPpi->Rcba = RCBA_BASE_ADDRESS; + PchPlatformPolicyPpi->AcpiBase = ACPI_BASE_ADDRESS; + PchPlatformPolicyPpi->GpioBase = GPIO_BASE_ADDRESS; + PchPlatformPolicyPpi->SataMode = SystemConfiguration->SataType; + PchPlatformPolicyPpi->EnableRmh = SystemConfiguration->PchUsbRmh; + + PchPlatformPolicyPpi->EhciPllCfgEnable = SystemConfiguration->EhciPllCfgEnable; + + + PchPlatformPolicyPpi->HpetConfig = HpetConfig; + PchPlatformPolicyPpi->PcieConfig = PcieConfig; + PchPlatformPolicyPpi->IoApicConfig = IoApicConfig; + + PchPlatformPolicyPpi->HpetConfig->Enable = SystemConfiguration->Hpet; + PchPlatformPolicyPpi->HpetConfig->Base = HPET_BASE_ADDRESS; + PchPlatformPolicyPpi->IoApicConfig->IoApicId = 0x01; + + // + // Set LPSS configuration according to setup value. + // + PchPlatformPolicyPpi->LpssConfig->LpssPciModeEnabled = SystemConfiguration->LpssPciModeEnabled; + + PchPlatformPolicyPpi->LpssConfig->Dma1Enabled = SystemConfiguration->LpssDma1Enabled; + PchPlatformPolicyPpi->LpssConfig->I2C0Enabled = SystemConfiguration->LpssI2C0Enabled; + PchPlatformPolicyPpi->LpssConfig->I2C1Enabled = SystemConfiguration->LpssI2C1Enabled; + PchPlatformPolicyPpi->LpssConfig->I2C2Enabled = SystemConfiguration->LpssI2C2Enabled; + PchPlatformPolicyPpi->LpssConfig->I2C3Enabled = SystemConfiguration->LpssI2C3Enabled; + PchPlatformPolicyPpi->LpssConfig->I2C4Enabled = SystemConfiguration->LpssI2C4Enabled; + PchPlatformPolicyPpi->LpssConfig->I2C5Enabled = SystemConfiguration->LpssI2C5Enabled; + PchPlatformPolicyPpi->LpssConfig->I2C6Enabled = SystemConfiguration->LpssI2C6Enabled; + + PchPlatformPolicyPpi->LpssConfig->Dma0Enabled = SystemConfiguration->LpssDma0Enabled;; + PchPlatformPolicyPpi->LpssConfig->Pwm0Enabled = SystemConfiguration->LpssPwm0Enabled; + PchPlatformPolicyPpi->LpssConfig->Pwm1Enabled = SystemConfiguration->LpssPwm1Enabled; + PchPlatformPolicyPpi->LpssConfig->Hsuart0Enabled = SystemConfiguration->LpssHsuart0Enabled; + PchPlatformPolicyPpi->LpssConfig->Hsuart1Enabled = SystemConfiguration->LpssHsuart1Enabled; + PchPlatformPolicyPpi->LpssConfig->SpiEnabled = SystemConfiguration->LpssSpiEnabled; + + + for (Index = 0; Index < PCH_PCIE_MAX_ROOT_PORTS; Index++) { + PchPlatformPolicyPpi->PcieConfig->PcieSpeed[Index] = SystemConfiguration->PcieRootPortSpeed[Index]; + } + + SpiHsfsReg = MmioRead32 (SPI_BASE_ADDRESS + R_PCH_SPI_HSFS); + if ((SpiHsfsReg & B_PCH_SPI_HSFS_FDV) == B_PCH_SPI_HSFS_FDV) { + MmioWrite32 (SPI_BASE_ADDRESS + R_PCH_SPI_FDOC, V_PCH_SPI_FDOC_FDSS_FSDM); + SpiFdodReg = MmioRead32 (SPI_BASE_ADDRESS + R_PCH_SPI_FDOD); + if (SpiFdodReg == V_PCH_SPI_FDBAR_FLVALSIG) { + } + // + // Disable codec ALC-262 + // + if (SystemConfiguration->DisableCodec262 == 1) { + IoBase = MmioRead32 (MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ) + R_PCH_LPC_IO_BASE) & B_PCH_LPC_IO_BASE_BAR; + MmioAnd32 ((UINTN) (IoBase + 0x270), (UINT32) (~0x07)); + } + } + + PchPlatformPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + PchPlatformPolicyPpiDesc->Guid = &gPchPlatformPolicyPpiGuid; + PchPlatformPolicyPpiDesc->Ppi = PchPlatformPolicyPpi; + + // + // Install PCH Platform Policy PPI + // + Status = (**PeiServices).InstallPpi ( + PeiServices, + PchPlatformPolicyPpiDesc + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_ERROR, "PchPolicySetupInit() - End\n")); +} + +EFI_STATUS +InstallPeiPchUsbPolicy ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + + EFI_PEI_PPI_DESCRIPTOR *PeiPchUsbPolicyPpiDesc; + PCH_USB_POLICY_PPI *PeiPchUsbPolicyPpi; + PCH_USB_CONFIG *UsbConfig; + EFI_PLATFORM_INFO_HOB PlatformInfo; + + // + // Allocate descriptor and PPI structures. Since these are dynamically updated + // we cannot do a global variable PPI. + // + Status = (*PeiServices)->AllocatePool (PeiServices, sizeof (EFI_PEI_PPI_DESCRIPTOR), (void **)&PeiPchUsbPolicyPpiDesc); + + + Status = (*PeiServices)->AllocatePool (PeiServices, sizeof (PCH_USB_POLICY_PPI), (void **)&PeiPchUsbPolicyPpi); + + + + Status = (*PeiServices)->AllocatePool (PeiServices, sizeof (PCH_USB_CONFIG), (void **)&UsbConfig); + + + // + // Initiate PCH USB policy. + // + PeiPchUsbPolicyPpi->Revision = PCH_USB_POLICY_PPI_REVISION_1; + UsbConfig->Usb20Settings[0].Enable = PCH_DEVICE_ENABLE; + UsbConfig->UsbPerPortCtl = PCH_DEVICE_DISABLE; + UsbConfig->Ehci1Usbr = PCH_DEVICE_DISABLE; + + // + // Initialize PlatformInfo HOB + // + ZeroMem (&PlatformInfo, sizeof(PlatformInfo)); + MultiPlatformInfoInit(PeiServices, &PlatformInfo); + + UsbConfig->Usb20OverCurrentPins[0] = PchUsbOverCurrentPin0; + + UsbConfig->Usb20OverCurrentPins[1] = PchUsbOverCurrentPin0; + + UsbConfig->Usb20OverCurrentPins[2] = PchUsbOverCurrentPin1; + + UsbConfig->Usb20OverCurrentPins[3] = PchUsbOverCurrentPin1; + + + // + // Enable USB Topology control and program the topology setting for every USB port + // See Platform Design Guide for description of topologies + // + // + // Port 0: ~10.9", Port 1: ~10.1", Port 2: ~11.2", Port 3: ~11.5", Port 4: ~3.7", Port 5: ~2.7", Port 6: ~4.1" + // Port 7: ~4.5", Port 8: ~10.7", Port 9: ~10.5", Port 10: ~4.2", Port 11: ~4.3", Port 12: ~3.1", Port 13: ~2.9" + // + + // + // Port 0: ~3.5", Port 1: ~4.1", Port 2: ~4.6", Port 3: ~4.6", Port 4: ~12.5", Port 5: ~12", Port 6: ~5.1" + // Port 7: ~5.1", Port 8: ~4.1", Port 9: ~4.1", Port 10: ~14.5", Port 11: ~12.8", Port 12: ~12.9", Port 13: ~14.6" + // + UsbConfig->Usb20PortLength[0] = 0x53; + UsbConfig->Usb20PortLength[1] = 0x49; + UsbConfig->Usb20PortLength[2] = 0x47; + UsbConfig->Usb20PortLength[3] = 0x80; + + PeiPchUsbPolicyPpi->Mode = EHCI_MODE; + + PeiPchUsbPolicyPpi->EhciMemBaseAddr = PcdGet32(PcdPeiIchEhciControllerMemoryBaseAddress); + + PeiPchUsbPolicyPpi->EhciMemLength = (UINT32) 0x400 * PchEhciControllerMax; + + PeiPchUsbPolicyPpi->UsbConfig = UsbConfig; + + PeiPchUsbPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + + PeiPchUsbPolicyPpiDesc->Guid = &gPchUsbPolicyPpiGuid; + + PeiPchUsbPolicyPpiDesc->Ppi = PeiPchUsbPolicyPpi; + + // + // Install PCH USB Policy PPI + // + Status = (**PeiServices).InstallPpi (PeiServices, PeiPchUsbPolicyPpiDesc); + + return Status; +} diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/PlatformEarlyInit.c b/Vlv2TbltDevicePkg/PlatformInitPei/PlatformEarlyInit.c new file mode 100644 index 0000000000..1a12c53e96 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/PlatformEarlyInit.c @@ -0,0 +1,1034 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PlatformEarlyInit.c + +Abstract: + + Do platform specific PEI stage initializations. + +--*/ + + +#include "PlatformEarlyInit.h" + +#ifdef __GNUC__ +#pragma GCC push_options +#pragma GCC optimize ("O0") +#else +#pragma optimize ("", off) +#endif + + + +static EFI_PEI_STALL_PPI mStallPpi = { + PEI_STALL_RESOLUTION, + Stall +}; + +static EFI_PEI_PPI_DESCRIPTOR mInstallStallPpi = { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiStallPpiGuid, + &mStallPpi +}; + +// +// The reserved SMBus addresses are defined in PlatformDxe.h file. +// +static UINT8 mSmbusRsvdAddresses[] = PLATFORM_SMBUS_RSVD_ADDRESSES; +static PEI_SMBUS_POLICY_PPI mSmbusPolicyPpi = { + SMBUS_BASE_ADDRESS, + SMBUS_BUS_DEV_FUNC, + PLATFORM_NUM_SMBUS_RSVD_ADDRESSES, + mSmbusRsvdAddresses +}; + +static EFI_PEI_PPI_DESCRIPTOR mInstallSmbusPolicyPpi = { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiSmbusPolicyPpiGuid, + &mSmbusPolicyPpi +}; +static PEI_SPEAKER_IF_PPI mSpeakerInterfacePpi = { + ProgramToneFrequency, + GenerateBeepTone +}; + +static EFI_PEI_PPI_DESCRIPTOR mInstallSpeakerInterfacePpi = { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiSpeakerInterfacePpiGuid, + &mSpeakerInterfacePpi +}; + +static EFI_PEI_RESET_PPI mResetPpi = { IchReset }; + + +static EFI_PEI_FIND_FV_PPI mEfiFindFvPpi = { + (EFI_PEI_FIND_FV_FINDFV)FindFv +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiPeiMasterBootModePpiGuid, + NULL + }, + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiPeiResetPpiGuid, + &mResetPpi + }, + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiFindFvPpiGuid, + &mEfiFindFvPpi + } +}; + +static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + &gEfiEndOfPeiSignalPpiGuid, + (EFI_PEIM_NOTIFY_ENTRY_POINT)EndOfPeiPpiNotifyCallback + }, + { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiMemoryDiscoveredPpiGuid, + (EFI_PEIM_NOTIFY_ENTRY_POINT)MemoryDiscoveredPpiNotifyCallback + } + +}; + + +/** + + Parse the status registers for figuring out the wake-up event and save it into + an GUID HOB which will be referenced later. However, modification is required + to meet the chipset register definition and the practical hardware design. Thus, + this is just an example. + + + @param PeiServices pointer to the PEI Service Table + @param EFI_SUCCESS Always return Success + + @retval None + + +**/ +EFI_STATUS +EFIAPI +GetWakeupEventAndSaveToHob ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + UINT16 Pm1Sts; + UINTN Gpe0Sts; + UINTN WakeEventData; + + // + // Read the ACPI registers + // + Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS); + Gpe0Sts = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_GPE0a_STS); + + // + // Figure out the wake-up event + // + if ((Pm1Sts & B_PCH_ACPI_PM1_STS_PWRBTN) != 0) { + WakeEventData = SMBIOS_WAKEUP_TYPE_POWER_SWITCH; + } else if (((Pm1Sts & B_PCH_ACPI_PM1_STS_WAK) != 0)) { + WakeEventData = SMBIOS_WAKEUP_TYPE_PCI_PME; + } else if (Gpe0Sts != 0) { + WakeEventData = SMBIOS_WAKEUP_TYPE_OTHERS; + } else { + WakeEventData = SMBIOS_WAKEUP_TYPE_UNKNOWN; + } + + DEBUG ((EFI_D_ERROR, "ACPI Wake Status Register: %04x\n", Pm1Sts)); + + return EFI_SUCCESS; +} + +EFI_STATUS +GetSetupVariable ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN SYSTEM_CONFIGURATION *SystemConfiguration + ) +{ + UINTN VariableSize; + EFI_STATUS Status; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; + + VariableSize = sizeof (SYSTEM_CONFIGURATION); + ZeroMem (SystemConfiguration, sizeof (SYSTEM_CONFIGURATION)); + + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&Variable + ); + ASSERT_EFI_ERROR (Status); + + // + // Use normal setup default from NVRAM variable, + // the Platform Mode (manufacturing/safe/normal) is handle in PeiGetVariable. + // + VariableSize = sizeof(SYSTEM_CONFIGURATION); + Status = Variable->GetVariable ( + Variable, + L"Setup", + &gEfiSetupVariableGuid, + NULL, + &VariableSize, + SystemConfiguration + ); + ASSERT_EFI_ERROR(Status); + return Status; +} + +EFI_STATUS +VlvPolicyInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN SYSTEM_CONFIGURATION *SystemConfiguration + ) +{ + EFI_STATUS Status; + EFI_PEI_PPI_DESCRIPTOR *mVlvPolicyPpiDesc; + VLV_POLICY_PPI *mVlvPolicyPpi; + + Status = (*PeiServices)->AllocatePool( + PeiServices, + sizeof (EFI_PEI_PPI_DESCRIPTOR), + (void **)&mVlvPolicyPpiDesc + ); + ASSERT_EFI_ERROR (Status); + + Status = (*PeiServices)->AllocatePool( + PeiServices, + sizeof (VLV_POLICY_PPI), + (void **)&mVlvPolicyPpi + ); + ASSERT_EFI_ERROR (Status); + + // + // Initialize PPI + // + (*PeiServices)->SetMem ((VOID *)mVlvPolicyPpi, sizeof (VLV_POLICY_PPI), 0); + mVlvPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + mVlvPolicyPpiDesc->Guid = &gVlvPolicyPpiGuid; + mVlvPolicyPpiDesc->Ppi = mVlvPolicyPpi; + mVlvPolicyPpi->GtConfig.PrimaryDisplay = SystemConfiguration->PrimaryVideoAdaptor; + mVlvPolicyPpi->GtConfig.IgdDvmt50PreAlloc = SystemConfiguration->IgdDvmt50PreAlloc; + mVlvPolicyPpi->GtConfig.ApertureSize = SystemConfiguration->IgdApertureSize; + mVlvPolicyPpi->GtConfig.GttSize = SystemConfiguration->GTTSize; + if (SystemConfiguration->PrimaryVideoAdaptor != 2) { + mVlvPolicyPpi->GtConfig.InternalGraphics = SystemConfiguration->Igd; + } else { + mVlvPolicyPpi->GtConfig.InternalGraphics = 0; + } + + + mVlvPolicyPpi->GtConfig.IgdTurboEn = 1; + + + mVlvPolicyPpi->PlatformData.FastBoot = SystemConfiguration->FastBoot; + mVlvPolicyPpi->PlatformData.DynSR = 1; + DEBUG ((EFI_D_ERROR, "Setup Option ISPEn: 0x%x\n", SystemConfiguration->ISPEn)); + mVlvPolicyPpi->ISPEn = SystemConfiguration->ISPEn; + DEBUG ((EFI_D_ERROR, "Setup Option ISPDevSel: 0x%x\n", SystemConfiguration->ISPDevSel)); + mVlvPolicyPpi->ISPPciDevConfig = SystemConfiguration->ISPDevSel; + if (SystemConfiguration->ISPEn == 0) { + mVlvPolicyPpi->ISPPciDevConfig = 0; + DEBUG ((EFI_D_ERROR, "Update Setup Option ISPDevSel: 0x%x\n", mVlvPolicyPpi->ISPPciDevConfig)); + } + Status = (*PeiServices)->InstallPpi( + PeiServices, + mVlvPolicyPpiDesc + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + + +EFI_STATUS +ConfigureSoCGpio ( + IN SYSTEM_CONFIGURATION *SystemConfiguration + ) +{ + + DEBUG ((EFI_D_ERROR, "ConfigureSoCGpio------------start\n")); + if (SystemConfiguration->eMMCBootMode== 1) {// Auto detection mode + DEBUG ((EFI_D_ERROR, "Auto detection mode------------start\n")); + + // + //Silicon Steppings + // + switch (PchStepping()) { + case PchA0: // SOC A0 and A1 + case PchA1: + DEBUG ((EFI_D_ERROR, "SOC A0/A1: eMMC 4.41 GPIO Configuration\n")); + SystemConfiguration->LpsseMMCEnabled = 1; + SystemConfiguration->LpsseMMC45Enabled = 0; + break; + case PchB0: // SOC B0 and later + default: + DEBUG ((EFI_D_ERROR, "SOC B0 and later: eMMC 4.5 GPIO Configuration\n")); + SystemConfiguration->LpsseMMCEnabled = 0; + SystemConfiguration->LpsseMMC45Enabled = 1; + break; + } + } else if (SystemConfiguration->eMMCBootMode == 2) { // eMMC 4.41 + DEBUG ((EFI_D_ERROR, "Force to eMMC 4.41 GPIO Configuration\n")); + SystemConfiguration->LpsseMMCEnabled = 1; + SystemConfiguration->LpsseMMC45Enabled = 0; + } else if (SystemConfiguration->eMMCBootMode == 3) { // eMMC 4.5 + DEBUG ((EFI_D_ERROR, "Force to eMMC 4.5 GPIO Configuration\n")); + SystemConfiguration->LpsseMMCEnabled = 0; + SystemConfiguration->LpsseMMC45Enabled = 1; + + } else { // Disable eMMC controllers + DEBUG ((EFI_D_ERROR, "Disable eMMC GPIO controllers\n")); + SystemConfiguration->LpsseMMCEnabled = 0; + SystemConfiguration->LpsseMMC45Enabled = 0; + } + + /* + 20.1.1 EMMC + SDMMC1_CLK - write 0x2003ED01 to IOBASE + 0x03E0 + SDMMC1_CMD - write 0x2003EC81 to IOBASE + 0x0390 + SDMMC1_D0 - write 0x2003EC81 to IOBASE + 0x03D0 + SDMMC1_D1 - write 0x2003EC81 to IOBASE + 0x0400 + SDMMC1_D2 - write 0x2003EC81 to IOBASE + 0x03B0 + SDMMC1_D3_CD_B - write 0x2003EC81 to IOBASE + 0x0360 + MMC1_D4_SD_WE - write 0x2003EC81 to IOBASE + 0x0380 + MMC1_D5 - write 0x2003EC81 to IOBASE + 0x03C0 + MMC1_D6 - write 0x2003EC81 to IOBASE + 0x0370 + MMC1_D7 - write 0x2003EC81 to IOBASE + 0x03F0 + MMC1_RESET_B - write 0x2003ED01 to IOBASE + 0x0330 + */ + if (SystemConfiguration->LpsseMMCEnabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x03E0, 0x2003ED01); //EMMC 4.41 + MmioWrite32 (IO_BASE_ADDRESS + 0x0390, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x03D0, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0400, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x03B0, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0360, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0380, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x03C0, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0370, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x03F0, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0330, 0x2003ED01); + } + + /* + eMMC 4.5 controller + SDMMC1_CLK - write 0x2003ED03 to IOBASE + 0x03E0 + SDMMC1_CMD - write 0x2003EC83 to IOBASE + 0x0390 + SDMMC1_D0 - write 0x2003EC83 to IOBASE + 0x03D0 + SDMMC1_D1 - write 0x2003EC83 to IOBASE + 0x0400 + SDMMC1_D2 - write 0x2003EC83 to IOBASE + 0x03B0 + SDMMC1_D3_CD_B - write 0x2003EC83 to IOBASE + 0x0360 + MMC1_D4_SD_WE - write 0x2003EC83 to IOBASE + 0x0380 + MMC1_D5 - write 0x2003EC83 to IOBASE + 0x03C0 + MMC1_D6 - write 0x2003EC83 to IOBASE + 0x0370 + MMC1_D7 - write 0x2003EC83 to IOBASE + 0x03F0 + MMC1_RESET_B - write 0x2003ED03 to IOBASE + 0x0330 + */ + if (SystemConfiguration->LpsseMMC45Enabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x03E0, 0x2003ED03); // EMMC 4.5 + MmioWrite32 (IO_BASE_ADDRESS + 0x0390, 0x2003EC83); + MmioWrite32 (IO_BASE_ADDRESS + 0x03D0, 0x2003EC83); + MmioWrite32 (IO_BASE_ADDRESS + 0x0400, 0x2003EC83); + MmioWrite32 (IO_BASE_ADDRESS + 0x03B0, 0x2003EC83); + MmioWrite32 (IO_BASE_ADDRESS + 0x0360, 0x2003EC83); + MmioWrite32 (IO_BASE_ADDRESS + 0x0380, 0x2003EC83); + MmioWrite32 (IO_BASE_ADDRESS + 0x03C0, 0x2003EC83); + MmioWrite32 (IO_BASE_ADDRESS + 0x0370, 0x2003EC83); + MmioWrite32 (IO_BASE_ADDRESS + 0x03F0, 0x2003EC83); + MmioWrite32 (IO_BASE_ADDRESS + 0x0330, 0x2003ED03); + + } + +// +// Change GPIOC_0 setting to allow MMIO access under Android. +// + IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL, + (IoRead32(GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL) & (UINT32)~BIT0)); + DEBUG ((EFI_D_ERROR, "ConfigureSoCGpio------------end\n")); + return EFI_SUCCESS; +} + +EFI_STATUS +MeasuredBootInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN SYSTEM_CONFIGURATION *SystemConfiguration + ) +{ + if (SystemConfiguration->MeasuredBootEnable) { + PcdSetBool (PcdMeasuredBootEnable, TRUE); + } else { + PcdSetBool (PcdMeasuredBootEnable, FALSE); + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +ConfigureLpssAndSccGpio ( + IN SYSTEM_CONFIGURATION *SystemConfiguration, + IN EFI_PLATFORM_INFO_HOB *PlatformInfo + ) +{ + /*One time configuration to each GPIO controller PSB_CONF register should be done before starting pad configuration: + GPIO SCORE - write 0x01001002 to IOBASE + 0x0700 + GPIO NCORE - write 0x01001002 to IOBASE + 0x0F00 + GPIO SSUS - write 0x01001002 to IOBASE + 0x1700 + */ + DEBUG ((EFI_D_ERROR, "ConfigureLpssAndSccGpio------------start\n")); + + /* + 19.1.1 PWM0 + PWM0 - write 0x2003CD01 to IOBASE + 0x00A0 + 19.1.2 PWM1 + PWM0 - write 0x2003CD01 to IOBASE + 0x00B0 + */ + if (SystemConfiguration->LpssPwm0Enabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x00A0, 0x2003CD01); + } else if (SystemConfiguration->LpssPwm0Enabled== 0) { + MmioWrite32 (IO_BASE_ADDRESS + 0x00A0, 0x2003CD00); + } + + if (SystemConfiguration->LpssPwm1Enabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x00B0, 0x2003CC01); + } else if (SystemConfiguration->LpssPwm1Enabled== 0) { + MmioWrite32 (IO_BASE_ADDRESS + 0x00B0, 0x2003CD00); + } + + /* + 19.1.3 UART1 + UART1_RXD-L - write 0x2003CC81 to IOBASE + 0x0020 + UART1_TXD-0 - write 0x2003CC81 to IOBASE + 0x0010 + UART1_RTS_B-1 - write 0x2003CC81 to IOBASE + 0x0000 + UART1_CTS_B-H - write 0x2003CC81 to IOBASE + 0x0040 + */ + if (SystemConfiguration->LpssHsuart0Enabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0020, 0x2003CC81); // uart1 + MmioWrite32 (IO_BASE_ADDRESS + 0x0010, 0x2003CC81); + if (SystemConfiguration->LpssHsuart0FlowControlEnabled== 0) { + DEBUG ((EFI_D_ERROR, "LpssHsuart0FlowControlEnabled[0]\n")); + MmioWrite32 (IO_BASE_ADDRESS + 0x0000, 0x2003CC80); + MmioWrite32 (IO_BASE_ADDRESS + 0x0040, 0x2003CC80); + } else { + DEBUG ((EFI_D_ERROR, "LpssHsuart0FlowControlEnabled[1]\n")); + MmioWrite32 (IO_BASE_ADDRESS + 0x0000, 0x2003CC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0040, 0x2003CC01);//W/A HSD 4752617 0x2003CC81 + } + } else if (SystemConfiguration->LpssHsuart0Enabled== 0) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0020, 0x2003CC80); // uart1 + MmioWrite32 (IO_BASE_ADDRESS + 0x0010, 0x2003CC80); + } + + + /* + 19.1.4 UART2 + UART2_RTS_B-1 - write 0x2003CC81 to IOBASE + 0x0090 + UART2_CTS_B-H - write 0x2003CC81 to IOBASE + 0x0080 + UART2_RXD-H - write 0x2003CC81 to IOBASE + 0x0060 + UART2_TXD-0 - write 0x2003CC81 to IOBASE + 0x0070 + */ + if (SystemConfiguration->LpssHsuart1Enabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0060, 0x2003CC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0070, 0x2003CC81); + + if (SystemConfiguration->LpssHsuart1FlowControlEnabled== 0) { + DEBUG ((EFI_D_ERROR, "LpssHsuart1FlowControlEnabled[0]\n")); + MmioWrite32 (IO_BASE_ADDRESS + 0x0090, 0x2003CC80); // UART2_RTS_B + MmioWrite32 (IO_BASE_ADDRESS + 0x0080, 0x2003CC80); // UART2_CTS_B + } else { + DEBUG ((EFI_D_ERROR, "LpssHsuart1FlowControlEnabled[1]\n")); + MmioWrite32 (IO_BASE_ADDRESS + 0x0090, 0x2003CC81); // uart2 + MmioWrite32 (IO_BASE_ADDRESS + 0x0080, 0x2003CC01); //W/A HSD 4752617 0x2003CC81 + } + } else if (SystemConfiguration->LpssHsuart1Enabled== 0) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0060, 0x2003CC80); + MmioWrite32 (IO_BASE_ADDRESS + 0x0070, 0x2003CC80); + } + + /* + 19.1.5 SPI + SPI1_CS0_B - write 0x2003CC81 to IOBASE + 0x0110 + SPI1_CLK - write 0x2003CD01 to IOBASE + 0x0100 + SPI1_MOSI - write 0x2003CC81 to IOBASE + 0x0130 + SPI1_MISO - write 0x2003CC81 to IOBASE + 0x0120 + */ + if (SystemConfiguration->LpssSpiEnabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0110, 0x2003CC81); // SPI + MmioWrite32 (IO_BASE_ADDRESS + 0x0100, 0x2003CD01); + MmioWrite32 (IO_BASE_ADDRESS + 0x0130, 0x2003CC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0120, 0x2003CC81); + } else if (SystemConfiguration->LpssSpiEnabled== 0) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0110, 0x2003cc80); + MmioWrite32 (IO_BASE_ADDRESS + 0x0100, 0x2003cc80); + MmioWrite32 (IO_BASE_ADDRESS + 0x0130, 0x2003cc80); + MmioWrite32 (IO_BASE_ADDRESS + 0x0120, 0x2003cc80); + } + + /* + 19.1.6 I2C0 + I2C0_SDA-OD-O - write 0x2003CC81 to IOBASE + 0x0210 + I2C0_SCL-OD-O - write 0x2003CC81 to IOBASE + 0x0200 + */ + if (SystemConfiguration->LpssI2C0Enabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0210, 0x2003C881); + MmioWrite32 (IO_BASE_ADDRESS + 0x0200, 0x2003C881); + } + /* + 19.1.7 I2C1 + I2C1_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x01F0 + I2C1_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x01E0 + */ + + if (SystemConfiguration->LpssI2C1Enabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x01F0, 0x2003C881); + MmioWrite32 (IO_BASE_ADDRESS + 0x01E0, 0x2003C881); + } + /* + 19.1.8 I2C2 + I2C2_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x01D0 + I2C2_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x01B0 + */ + if (SystemConfiguration->LpssI2C2Enabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x01D0, 0x2003C881); + MmioWrite32 (IO_BASE_ADDRESS + 0x01B0, 0x2003C881); + } + /* + 19.1.9 I2C3 + I2C3_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x0190 + I2C3_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x01C0 + */ + if (SystemConfiguration->LpssI2C3Enabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0190, 0x2003C881); + MmioWrite32 (IO_BASE_ADDRESS + 0x01C0, 0x2003C881); + } + /* + 19.1.10 I2C4 + I2C4_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x01A0 + I2C4_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x0170 + */ + if (SystemConfiguration->LpssI2C4Enabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x01A0, 0x2003C881); + MmioWrite32 (IO_BASE_ADDRESS + 0x0170, 0x2003C881); + } + /* + 19.1.11 I2C5 + I2C5_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x0150 + I2C5_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x0140 + */ + //touch 1.7M support on i2c5(from 0) need 2k PULL-UP. + if (SystemConfiguration->LpssI2C5Enabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0150, 0x2003C881); + MmioWrite32 (IO_BASE_ADDRESS + 0x0140, 0x2003C881); + } else if(SystemConfiguration->LpssI2C5Enabled== 0) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0150, 0x2003C880); + MmioWrite32 (IO_BASE_ADDRESS + 0x0140, 0x2003C880); + } + /* + 19.1.12 I2C6 + I2C6_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x0180 + I2C6_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x0160 + */ + if (SystemConfiguration->LpssI2C6Enabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0180, 0x2003C881); + MmioWrite32 (IO_BASE_ADDRESS + 0x0160, 0x2003C881); + } else if (SystemConfiguration->LpssI2C6Enabled== 0) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0180, 0x2003C880); + MmioWrite32 (IO_BASE_ADDRESS + 0x0160, 0x2003C880); + } + + + /* + 20.1.2 SDIO + SDMMC2_CLK - write 0x2003ED01 to IOBASE + 0x0320 + SDMMC2_CMD - write 0x2003EC81 to IOBASE + 0x0300 + SDMMC2_D0 - write 0x2003EC81 to IOBASE + 0x0350 + SDMMC2_D1 - write 0x2003EC81 to IOBASE + 0x02F0 + SDMMC2_D2 - write 0x2003EC81 to IOBASE + 0x0340 + SDMMC2_D3_CD_B - write 0x2003EC81 to IOBASE + 0x0310 + */ + if (SystemConfiguration->LpssSdioEnabled== 1) { + MmioWrite32 (IO_BASE_ADDRESS + 0x0320, 0x2003ED01);//SDIO + MmioWrite32 (IO_BASE_ADDRESS + 0x0300, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0350, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x02F0, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0340, 0x2003EC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0310, 0x2003EC81); + } + + /* + 20.1.3 SD Card + SDMMC3_1P8_EN - write 0x2003CD01 to IOBASE + 0x03F0 + SDMMC3_CD_B - write 0x2003CC81 to IOBASE + 0x03A0 + SDMMC3_CLK - write 0x2003CD01 to IOBASE + 0x02B0 + SDMMC3_CMD - write 0x2003CC81 to IOBASE + 0x02C0 + SDMMC3_D0 - write 0x2003CC81 to IOBASE + 0x02E0 + SDMMC3_D1 - write 0x2003CC81 to IOBASE + 0x0290 + SDMMC3_D2 - write 0x2003CC81 to IOBASE + 0x02D0 + SDMMC3_D3 - write 0x2003CC81 to IOBASE + 0x02A0 + SDMMC3_PWR_EN_B - write 0x2003CC81 to IOBASE + 0x0690 + SDMMC3_WP - write 0x2003CC82 to IOBASE + 0x0160 + */ + if (SystemConfiguration->LpssSdcardEnabled == 1) { + if (!((PlatformInfo->BoardId == BOARD_ID_BL_FFRD && PlatformInfo->BoardRev== PR11) && (SystemConfiguration->CfioPnpSettings == 1))) { + MmioWrite32 (IO_BASE_ADDRESS + 0x05F0, 0x2003CD01);//SDCARD + MmioWrite32 (IO_BASE_ADDRESS + 0x02B0, 0x2003CD01); + MmioWrite32 (IO_BASE_ADDRESS + 0x02C0, 0x2003CC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x02E0, 0x2003CC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0290, 0x2003CC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x02D0, 0x2003CC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x02A0, 0x2003CC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0690, 0x2003CC81); + MmioWrite32 (IO_BASE_ADDRESS + 0x0650, 0x2003CC82); //GPIOC_7 set to WP Pin + } + } + + + DEBUG ((EFI_D_ERROR, "ConfigureLpssAndSccGpio------------end\n")); + return EFI_SUCCESS; +} + +EFI_STATUS +ConfigureLpeGpio ( + IN SYSTEM_CONFIGURATION *SystemConfiguration + ) +{ + DEBUG ((EFI_D_ERROR, "ConfigureLpeGpio------------start\n")); + + if (SystemConfiguration->PchAzalia == 0) { + MmioAndThenOr32 (IO_BASE_ADDRESS + 0x220, (UINT32)~(0x7), (UINT32) (0x01)); + MmioAndThenOr32 (IO_BASE_ADDRESS + 0x250, (UINT32)~(0x7), (UINT32) (0x01)); + MmioAndThenOr32 (IO_BASE_ADDRESS + 0x240, (UINT32)~(0x7), (UINT32) (0x01)); + MmioAndThenOr32 (IO_BASE_ADDRESS + 0x260, (UINT32)~(0x7), (UINT32) (0x01)); + MmioAndThenOr32 (IO_BASE_ADDRESS + 0x270, (UINT32)~(0x7), (UINT32) (0x01)); + MmioAndThenOr32 (IO_BASE_ADDRESS + 0x230, (UINT32)~(0x7), (UINT32) (0x01)); + MmioAndThenOr32 (IO_BASE_ADDRESS + 0x280, (UINT32)~(0x7), (UINT32) (0x01)); + MmioAndThenOr32 (IO_BASE_ADDRESS + 0x540, (UINT32)~(0x7), (UINT32) (0x01)); + } + + DEBUG ((EFI_D_ERROR, "ConfigureLpeGpio------------end\n")); + + return EFI_SUCCESS; +} + +EFI_STATUS +ConfigureSciSmiGpioRout ( + IN EFI_PLATFORM_INFO_HOB *PlatformInfo) +{ + UINT32 GPI_Routing; + + GPI_Routing = MmioRead32 (PMC_BASE_ADDRESS + R_PCH_PMC_GPI_ROUT); + + // + // For FAB3, Route GPIO_CORE 0 to cause Runtime SCI, GPIO_SUS 0 to cause Wake SCI and GPIO_SUS 7 to cause EXTSMI + // + if(PlatformInfo->BoardRev == 3) { + GPI_Routing = GPI_Routing & 0xfffc3ffc; + GPI_Routing = GPI_Routing | 0x00024002; + } + + // + // For FAB2/1, Route GPIO_CORE 7 to cause Runtime SCI, GPIO_SUS 0 to cause Wake SCI and GPIO_SUS 7 to cause EXTSMI + // + else { + GPI_Routing = GPI_Routing & 0x3fff3ffc; + GPI_Routing = GPI_Routing | 0x80004002; + } + MmioWrite32((PMC_BASE_ADDRESS + R_PCH_PMC_GPI_ROUT), GPI_Routing); + + return EFI_SUCCESS; +} + +EFI_STATUS +ConfigureMipiCsi ( + VOID) +{ + // + //Configure the platform clock for MIPI-CSI usage + //PLT_CLK0 + // + MmioAndThenOr32 (IO_BASE_ADDRESS + 0x6a0, (UINT32)~(0x7), (UINT32) (0x01)); + + // + //PLT_CLK1 + // + MmioAndThenOr32 (IO_BASE_ADDRESS + 0x570, (UINT32)~(0x7), (UINT32) (0x01)); + + // + //PLT_CLK2 + // + MmioAndThenOr32 (IO_BASE_ADDRESS + 0x5B0, (UINT32)~(0x7), (UINT32) (0x01)); + + return EFI_SUCCESS; +} + +EFI_STATUS +ConfigureUSBULPI ( + VOID) +{ + // + //Configure USB ULPI + //USB_ULPI_0_CLK + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x338, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x330, (UINT32)~(0x187), (UINT32) (0x101)); + + // + //USB_ULPI_0_DATA0 + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x388, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x380, (UINT32)~(0x187), (UINT32) (0x101)); + + // + //USB_ULPI_0_DATA1 + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x368, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x360, (UINT32)~(0x187), (UINT32) (0x101)); + + // + //USB_ULPI_0_DATA2 + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x318, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x310, (UINT32)~(0x187), (UINT32) (0x101)); + + // + //USB_ULPI_0_DATA3 + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x378, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x370, (UINT32)~(0x187), (UINT32) (0x101)); + + // + //USB_ULPI_0_DATA4 + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x308, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x300, (UINT32)~(0x187), (UINT32) (0x101)); + + // + //USB_ULPI_0_DATA5 + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x398, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x390, (UINT32)~(0x187), (UINT32) (0x101)); + + // + //USB_ULPI_0_DATA6 + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x328, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x320, (UINT32)~(0x187), (UINT32) (0x101)); + + // + //USB_ULPI_0_DATA7 + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x3a8, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x3a0, (UINT32)~(0x187), (UINT32) (0x101)); + + // + //USB_ULPI_0_DIR + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x348, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x340, (UINT32)~(0x187), (UINT32) (0x81)); + + // + //USB_ULPI_0_NXT + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x358, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x350, (UINT32)~(0x187), (UINT32) (0x101)); + + // + //USB_ULPI_0_STP + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x3b8, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x3b0, (UINT32)~(0x187), (UINT32) (0x81)); + + // + //USB_ULPI_0_REFCLK + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x288, (UINT32)~(0x7), (UINT32) (GPI)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x280, (UINT32)~(0x187), (UINT32) (0x101)); + + return EFI_SUCCESS; +} + +EFI_STATUS +DisableRTD3 ( + VOID) +{ + // + //Disable RTD3 + // + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x210, (UINT32)~(0x0f000007), (UINT32) (0x00)); + MmioAndThenOr32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + 0x1e0, (UINT32)~(0x0f000007), (UINT32) (0x00)); + + return EFI_SUCCESS; +} + +/** + Platform specific initializations in stage1. + + @param FfsHeader Pointer to the PEIM FFS file header. + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS Operation completed successfully. + @retval Otherwise Platform initialization failed. +**/ +EFI_STATUS +EFIAPI +PlatformEarlyInitEntry ( + + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + SYSTEM_CONFIGURATION SystemConfiguration; + EFI_PLATFORM_INFO_HOB *PlatformInfo; + EFI_PEI_HOB_POINTERS Hob; + EFI_PLATFORM_CPU_INFO PlatformCpuInfo; + + // + // Initialize SmbusPolicy PPI + // + Status = (*PeiServices)->InstallPpi(PeiServices, &mInstallSmbusPolicyPpi); + ASSERT_EFI_ERROR (Status); + + // + // Initialize Stall PPIs + // + Status = (*PeiServices)->InstallPpi (PeiServices, &mInstallStallPpi); + ASSERT_EFI_ERROR (Status); + + // + // Initialize platform PPIs + // + Status = (*PeiServices)->InstallPpi (PeiServices, &mInstallSpeakerInterfacePpi); + ASSERT_EFI_ERROR (Status); + + // + // Variable initialization + // + ZeroMem(&PlatformCpuInfo, sizeof(EFI_PLATFORM_CPU_INFO)); + + // + // Set the some PCI and chipset range as UC + // And align to 1M at leaset + // + Hob.Raw = GetFirstGuidHob (&gEfiPlatformInfoGuid); + ASSERT (Hob.Raw != NULL); + PlatformInfo = GET_GUID_HOB_DATA(Hob.Raw); + + // + // Initialize PlatformInfo HOB + // + MultiPlatformInfoInit(PeiServices, PlatformInfo); + + // + // Do basic MCH init + // + MchInit (PeiServices); + + // + // Set the new boot mode + // + Status = UpdateBootMode (PeiServices, PlatformInfo); + ASSERT_EFI_ERROR (Status); + + SetPlatformBootMode (PeiServices, PlatformInfo); + + // + // Get setup variable. This can only be done after BootMode is updated + // + GetSetupVariable (PeiServices, &SystemConfiguration); + + CheckOsSelection(PeiServices, &SystemConfiguration); + + // + // Update PlatformInfo HOB according to setup variable + // + PlatformInfoUpdate(PeiServices, PlatformInfo, &SystemConfiguration); + + InitializePlatform (PeiServices, PlatformInfo, &SystemConfiguration); + + // + // Initialize VlvPolicy PPI + // + Status = VlvPolicyInit (PeiServices, &SystemConfiguration); + ASSERT_EFI_ERROR (Status); + + // + // Soc specific GPIO setting + // + ConfigureSoCGpio(&SystemConfiguration); + + // + // Baylake Board specific. + // + if (PlatformInfo->BoardId == BOARD_ID_BL_RVP || + PlatformInfo->BoardId == BOARD_ID_BL_FFRD || + PlatformInfo->BoardId == BOARD_ID_BL_FFRD8 || + PlatformInfo->BoardId == BOARD_ID_BL_RVP_DDR3L || + PlatformInfo->BoardId == BOARD_ID_BL_STHI || + PlatformInfo->BoardId == BOARD_ID_BB_RVP || + PlatformInfo->BoardId == BOARD_ID_BS_RVP || + PlatformInfo->BoardId == BOARD_ID_MINNOW2 || + PlatformInfo->BoardId == BOARD_ID_CVH) { + ConfigureLpssAndSccGpio(&SystemConfiguration, PlatformInfo); + + } + + + // + // Configure LPE + // Alpine Valley and Bayley Bay board specific + // + ConfigureLpeGpio(&SystemConfiguration); + + // + // Bayley Bay Board specific. + // + ConfigureSciSmiGpioRout(PlatformInfo); + if (SystemConfiguration.LpssI2C3Enabled == 1) { + ConfigureMipiCsi(); + } + + + // + // Do basic CPU init + // + Status = PlatformCpuInit (PeiServices, &SystemConfiguration, &PlatformCpuInfo); + + // + // Perform basic SSA related platform initialization + // + PlatformSsaInit (&SystemConfiguration,PeiServices); + + + // + // Do basic PCH init + // + Status = PlatformPchInit (&SystemConfiguration, PeiServices, PlatformInfo->PlatformType); + ASSERT_EFI_ERROR (Status); + + // + // Initialize platform PPIs + // + Status = (*PeiServices)->InstallPpi (PeiServices, &mPpiList[0]); + ASSERT_EFI_ERROR (Status); + + if (PlatformInfo->BoardId != BOARD_ID_CVH) { + InstallPlatformClocksNotify (PeiServices); + InstallPlatformSysCtrlGPIONotify(PeiServices); + } + + // + // Initialize platform PPIs + // + Status = (*PeiServices)->NotifyPpi(PeiServices, &mNotifyList[0]); + ASSERT_EFI_ERROR (Status); + + // + // Initialize Measured Boot + // + Status = MeasuredBootInit (PeiServices, &SystemConfiguration); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + + Return the mainblockcompact Fv. + + @param FvNumber Our enumeration of the firmware volumes we care about. + + @param FvAddress Base Address of the memory containing the firmware volume + + @retval EFI_SUCCESS + @retval EFI_NOT_FOUND + +**/ +EFI_STATUS +EFIAPI +FindFv ( + IN EFI_PEI_FIND_FV_PPI *This, + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT UINT8 *FvNumber, + OUT EFI_FIRMWARE_VOLUME_HEADER **FVAddress + ) +{ + // + // At present, we only have one Fv to search + // + if (*FvNumber == 0) { + *FvNumber = 1; + *FVAddress = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FixedPcdGet32 (PcdFlashFvMainBase); + return EFI_SUCCESS; + } + else if (*FvNumber == 1) { + *FvNumber = 2; + *FVAddress = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FixedPcdGet32 (PcdFlashFvRecovery2Base); + return EFI_SUCCESS; + } + else { // Not the one Fv we care about + return EFI_NOT_FOUND; + } +} + +EFI_STATUS +EFIAPI +CpuOnlyReset ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ +// MsgBus32Write(CDV_UNIT_PUNIT, PUNIT_CPU_RST, 0x01) +#ifdef __GNUC__ + __asm__ + ( + "xorl %ecx, %ecx\n" + "1:hlt; hlt; hlt\n" + "jmp 1b\n" + ); +#else + _asm { + xor ecx, ecx + HltLoop: + hlt + hlt + hlt + loop HltLoop + } +#endif + // + // If we get here we need to mark it as a failure. + // + return EFI_UNSUPPORTED; +} + + +#ifdef __GNUC__ +#pragma GCC pop_options +#else +#pragma optimize ("", on) +#endif diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/PlatformEarlyInit.h b/Vlv2TbltDevicePkg/PlatformInitPei/PlatformEarlyInit.h new file mode 100644 index 0000000000..c2cdfa3900 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/PlatformEarlyInit.h @@ -0,0 +1,1502 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + PlatformEarlyInit.h + +Abstract: + + Platform Early Stage header file + + + +--*/ + +/*++ + This file contains an 'Intel Peripheral Driver' and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +--*/ + +#ifndef _EFI_PLATFORM_EARLY_INIT_H_ +#define _EFI_PLATFORM_EARLY_INIT_H_ + +#define EFI_FORWARD_DECLARATION(x) typedef struct _##x x +#include +#include "PlatformBaseAddresses.h" +#include "PchAccess.h" +#include "VlvAccess.h" +#include "SetupMode.h" +#include "PlatformBootMode.h" +#include "Platform.h" +#include "LegacySpeaker.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SMC_LAN_ON 0x46 +#define SMC_LAN_OFF 0x47 +#define SMC_DEEP_S3_STS 0xB2 + + + + +// +// Wake Event Types +// +#define SMBIOS_WAKEUP_TYPE_RESERVED 0x00 +#define SMBIOS_WAKEUP_TYPE_OTHERS 0x01 +#define SMBIOS_WAKEUP_TYPE_UNKNOWN 0x02 +#define SMBIOS_WAKEUP_TYPE_APM_TIMER 0x03 +#define SMBIOS_WAKEUP_TYPE_MODEM_RING 0x04 +#define SMBIOS_WAKEUP_TYPE_LAN_REMOTE 0x05 +#define SMBIOS_WAKEUP_TYPE_POWER_SWITCH 0x06 +#define SMBIOS_WAKEUP_TYPE_PCI_PME 0x07 +#define SMBIOS_WAKEUP_TYPE_AC_POWER_RESTORED 0x08 + +#define EFI_CPUID_VIRT_PHYS_ADDRESS_SIZE 0x80000008 + +// +// Defines for stall ppi +// +#define PEI_STALL_RESOLUTION 1 + +// +// Used in PEI memory test routines +// +#define MEMORY_TEST_COVER_SPAN 0x40000 +#define MEMORY_TEST_PATTERN 0x5A5A5A5A + +#define EFI_LOW_BEEP_FREQUENCY 0x31B +#define EFI_HIGH_BEEP_FREQUENCY 0x254 + +// +// General Purpose Constants +// +#define ICH_ACPI_TIMER_MAX_VALUE 0x1000000 //The timer is 24 bit overflow + + + +// +// +// GPIO Register Settings for ValleyFalls (Tablet) +// +// +// IO Space configyuration registers +// Field Descriptions: +// USE: Defines the pin's usage model: GPIO (G) or Native (N) mode. +// I/O: Defines whether GPIOs are inputs (I) or outputs (O). +// (Note: Only meaningful for pins used as GPIOs.) +// LVL: This field gives you the initial value for "output" GPIO's. +// (Note: The output level is dependent upon whether the pin is inverted.) +// TPE: Defines whether Trigger Positive Edge Enable. +// TNE: Defines whether Trigger Negative Edge Enable. +// WAKE_EN: only support in SUS community +// (Note: Only affects the level sent to the GPE logic and does not +// affect the level read through the GPIO registers.) +// +// +// Memory spcae configuration registers +// +// Field Descriptions: +// PAD releated: +// PAD_CONF0 +// PAD_CONF1 +// PAD_VAL +// PAD_DFT +// +// Notes: +// 1. N = Native , G = GPIO , I = Input, O = Output, - = BOTH/NOT SURE +// +// Signal UsedAs USE I/O LVL TPE TNE PCONF0 PCONF1 PVAL PDFT +// ------------------------------------------------------------------------------------------------------------------------- +// GPIO0 UART1_RXD-L N I - - - cd29h - - - +// GPIO1 UART1_TXD-0 N O - - - cd29h - - - +// *GPIO2 UART1_RTS_B-1 N I - - - cca9h - - - +// *GPIO3 UART1_CTS_B-H N O - - - cca9h - - - + +// GPIO4 I2C1_SDA-OD-O N - - - - cca9h - - - +// GPIO5 I2C1_SCL-OD-O N - - - - cca9h - - - +// GPIO6 I2S_SYSCLK-0 N O - - - 8d51h - - - +// GPIO7 I2S_L_R-0 (SP) N O - - - 8cd1h - - - +// GPIO8 I2S_DATA_OUT-0 N O - - - 8cd1h - - - +// GPIO9 I2S_SDATA_IN-L N I - - - 8cd1h - - - + +// GPIO10 PCM_CLK-0 N O - - - 8d51h - - - +// GPIO11 PCM_FSYNC-0 (SP) N O - - - 8cd1h - - - +// GPIO12 PCM_DATA_OUT-0 (SP) N O - - - 8cd1h - - - +// GPIO13 PCM_DATA_IN-L N I - - - 8d51h - - - + +// GPIO14 SATA_GP0 N - - - - - - - - +// GPIO15 I2C2_SDA-OD-O/I N - - - - ccaah - - - + +// GPIO16 SATA_LEDN N O - - - - - - - +// GPIO17 UART2_RTS_B-1 N I - - - cd2ah - - - +// GPIO18 UART2_CTS_B-H N O - - - ccaah - - - +// GPIO19 UART2_RXD-H N I - - - ccaah - - - + +// GPIO20 I2C2_SCL-OD-O/I N - - - - ccaah - - - +// GPIO21 **PCIE_CLKREQ4B N - - - - - - - - +// GPIO22 UART2_TXD-0 N O - - - ccaah - - - +// GPIO23 FLEX_CLK_SE1 N - - - - - - - - + +// GPIO24 SPI0_SCK-0 N O - - - 8d02h - - - +// GPIO25 SPI0_CS-1 N O - - - 8d02h - - - +// GPIO26 SPI0_MOSI-0 N O - - - 8d02h - - - +// GPIO27 SPI0_MISO-L N I - - - 8d02h - - - + +// GPIO28 UART3_RXD-L N I - - - - - - - +// GPIO29 UART3_TXD-0 N O - - - - - - - +// GPIO30 UART4_RXD-L N I - - - - - - - +// GPIO31 UART4_TXD-0 N O - - - - - - - + +// GPIO32 SDMMC1_CLK N - - - - 208d51h - - - +// GPIO33 SDMMC1_D0 N - - - - 8cd1h - - - +// GPIO34 SDMMC1_D1 N - - - - 8cd1h - - - +// GPIO35 SDMMC1_D2 N - - - - 8cd1h - - - +// GPIO36 SDMMC1_D3_CD_B N - - - - 8cd1h - - - +// GPIO37 MMC1_D4_SD_WE N - - - - 8cd1h - - - +// GPIO38 MMC1_D5 N - - - - 8cd1h - - - +// GPIO39 MMC1_D6 N - - - - 8cd1h - - - +// GPIO40 MMC1_D7 N - - - - 8cd1h - - - +// GPIO41 SDMMC1_CMD N - - - - 8cd1h - - - +// GPIO42 MMC1_RESET_B N - - - - 208d51h - - - + +// GPIO43 SDMMC2_CLK N - - - - 208d51h - - - +// GPIO44 SDMMC2_D0 N - - - - 8cd1h - - - +// GPIO45 SDMMC2_D1 N - - - - 8cd1h - - - +// GPIO46 SDMMC2_D2 N - - - - 8cd1h - - - +// GPIO47 SDMMC2_D3_CD_B N - - - - 8cd1h - - - +// GPIO48 SDMMC2_CMD N - - - - 8cd1h - - - + +// GPIO49 SDMMC3_CLK N - - - - 8d51h - - - +// GPIO50 SDMMC3_D0 N - - - - 8cd1h - - - +// GPIO51 SDMMC3_D1 N - - - - 8cd1h - - - +// GPIO52 SDMMC3_D2 N - - - - 8cd1h - - - +// GPIO53 SDMMC3_D3 N - - - - 8cd1h - - - +// GPIO54 SDMMC3_CD_B N - - - - cca9h - - - +// GPIO55 SDMMC3_CMD N - - - - 8cd1h - - - +// GPIO56 SDMMC3_1P8_EN N - - - - cd29h - - - + +// GPIO57 LPC_AD0 N - - - - - - - - +// GPIO58 LPC_AD1 N - - - - - - - - +// GPIO59 LPC_AD2 N - - - - - - - - +// GPIO60 LPC_AD3 N - - - - - - - - +// GPIO61 LPC_FRAMEB N O - - - - - - - +// GPIO62 LPC_CLKOUT0 N O - - - - - - - +// GPIO63 LPC_CLKOUT1 N O - - - - - - - +// GPIO64 LPC_CLKRUNB N - - - - - - - - + +// GPIO65 SMB_DATA N - - - - - - - - +// GPIO66 SMB_CLK N - - - - - - - - +// GPIO67 SMB_ALERTB N - - - - - - - - + +// GPIO68 ILB_SEIRQ N - - - - - - - - +// GPIO69 SPKR N O - - - - - - - + +//SUS WELL + +//GPIO_SUS0 BT_WAKEUP_VLV N O - - - CCA8h - - - +//GPIO_SUS1 BT_CLOCK_REQ N O - - - CCA8h - - - +//GPIO_SUS2 WIFI_PWR_EN N O - - - CCA8h - - - +//GPIO_SUS3 SD_CARD_PWR_EN N O - - - CD28h - - - +//GPIO_SUS4 GPIO_SUS4 N O - - - CD28h - - - +//GPIO_SUS5 GPIO_SUS5 N O - - - CD28h - - - +//GPIO_SUS6 SUSPWRDNACK N O - - - 8850h - - - +//GPIO_SUS7 PMU_SLP_DDRVTT_B N O - - - 8850h - - - +//GPIO_SUS8 PMU_WAKE_B N O - - - CCA8h - - - +//GPIO_SUS9 PMU_PWRBTN_B N O - - - CCA8h - - - +//GPIO_SUS10 PMU_WAKE_LAN_B N O - - - CCA8h - - - +//GPIO_SUS11 SUS_STAT_B N O - - - C828h - - - +//GPIO_SUS12 GPIO_SUS12 N O - - - C828h - - - +//GPIO_SUS13 USB_OC0_B-20K,H N O - - - CCA8h - - - +//GPIO_SUS14 GPIO_SUS14 N O - - - CCA8h - - - +//GPIO_SUS15 SPI_CS1_B-20K,H N O - - - 8C80h - - - +//GPIO_SUS16 PMU_SUSCLK N O - - - C828h - - - +// + + +#define VF_TAB_GPIO_USE_SEL_VAL_0_31 0x00000000 +#define VF_TAB_GPIO_USE_SEL_VAL_32_63 0x00000000 +#define VF_TAB_GPIO_USE_SEL_VAL_64_70 0x00000000 +#define VF_TAB_GPIO_USE_SEL_VAL_SUS 0x00000000 + +// +//1010 --00 0100 01-- 0101 --0- 0001 1010 +// +#define VF_TAB_GPIO_IO_SEL_VAL_0_31 0x00000000 // BIT30 | BIT28 | BIT27 | BIT19 | BIT17 | BIT13 | BIT9 | BIT2 | BIT0 +#define VF_TAB_GPIO_IO_SEL_VAL_32_63 0x00000000 +#define VF_TAB_GPIO_IO_SEL_VAL_64_70 0x00000000 +#define VF_TAB_GPIO_IO_SEL_VAL_SUS 0x00000000 + + +#define VF_TAB_GPIO_LVL_VAL_0_31 0x00000000 +#define VF_TAB_GPIO_LVL_VAL_32_63 0x00000000 +#define VF_TAB_GPIO_LVL_VAL_64_70 0x00000000 +#define VF_TAB_GPIO_LVL_VAL_SUS 0x00000000 + +#define VF_TAB_GPIO_TPE_VAL_0_31 0x00000000 +#define VF_TAB_GPIO_TPE_VAL_SUS 0x00000000 + +#define VF_TAB_GPIO_TNE_VAL_0_31 0x00000000 +#define VF_TAB_GPIO_TNE_VAL_SUS 0x00000000 + +#define VF_TAB_GPIO_TS_VAL_0_31 0x00000000 +#define VF_TAB_GPIO_TS_VAL_SUS 0x00000000 + + +// +// Memory space registers +// + +// +// CONF0 +// +#define VF_TAB_PAD_CONF0_GPIO0 0xcd29 +#define VF_TAB_PAD_CONF0_GPIO1 0xcd29 +#define VF_TAB_PAD_CONF0_GPIO2 0xcca9 +#define VF_TAB_PAD_CONF0_GPIO3 0xcca9 +#define VF_TAB_PAD_CONF0_GPIO4 0xcca9 +#define VF_TAB_PAD_CONF0_GPIO5 0xcca9 +#define VF_TAB_PAD_CONF0_GPIO6 0x8d51 +#define VF_TAB_PAD_CONF0_GPIO7 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO8 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO9 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO10 0x8d51 +#define VF_TAB_PAD_CONF0_GPIO11 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO12 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO13 0x8d51 +#define VF_TAB_PAD_CONF0_GPIO14 0xCCA8 +#define VF_TAB_PAD_CONF0_GPIO15 0xccaa +#define VF_TAB_PAD_CONF0_GPIO16 0xC828 +#define VF_TAB_PAD_CONF0_GPIO17 0xcd2a +#define VF_TAB_PAD_CONF0_GPIO18 0xccaa +#define VF_TAB_PAD_CONF0_GPIO19 0xccaa +#define VF_TAB_PAD_CONF0_GPIO20 0xccaa +#define VF_TAB_PAD_CONF0_GPIO21 0xCCA9 +#define VF_TAB_PAD_CONF0_GPIO22 0xccaa +#define VF_TAB_PAD_CONF0_GPIO23 0xCD2A +#define VF_TAB_PAD_CONF0_GPIO24 0x8d02 +#define VF_TAB_PAD_CONF0_GPIO25 0x8d02 +#define VF_TAB_PAD_CONF0_GPIO26 0x8d02 +#define VF_TAB_PAD_CONF0_GPIO27 0x8d02 +#define VF_TAB_PAD_CONF0_GPIO28 0x8D02 +#define VF_TAB_PAD_CONF0_GPIO29 0x8D02 +#define VF_TAB_PAD_CONF0_GPIO30 0x8D00 +#define VF_TAB_PAD_CONF0_GPIO31 0xCD2A +#define VF_TAB_PAD_CONF0_GPIO32 0x208d51 +#define VF_TAB_PAD_CONF0_GPIO33 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO34 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO35 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO36 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO37 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO38 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO39 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO40 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO41 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO42 0x208d51 +#define VF_TAB_PAD_CONF0_GPIO43 0x208d51 +#define VF_TAB_PAD_CONF0_GPIO44 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO45 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO46 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO47 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO48 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO49 0x8d51 +#define VF_TAB_PAD_CONF0_GPIO50 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO51 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO52 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO53 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO54 0xcca9 +#define VF_TAB_PAD_CONF0_GPIO55 0x8cd1 +#define VF_TAB_PAD_CONF0_GPIO56 0xcd29 +#define VF_TAB_PAD_CONF0_GPIO57 0x8C80 +#define VF_TAB_PAD_CONF0_GPIO58 0x8C80 +#define VF_TAB_PAD_CONF0_GPIO59 0x8C80 +#define VF_TAB_PAD_CONF0_GPIO60 0x8C80 +#define VF_TAB_PAD_CONF0_GPIO61 0x8800 +#define VF_TAB_PAD_CONF0_GPIO62 0x8D00 +#define VF_TAB_PAD_CONF0_GPIO63 0x8800 +#define VF_TAB_PAD_CONF0_GPIO64 0x8800 +#define VF_TAB_PAD_CONF0_GPIO65 0xC828 +#define VF_TAB_PAD_CONF0_GPIO66 0xC828 +#define VF_TAB_PAD_CONF0_GPIO67 0xC828 +#define VF_TAB_PAD_CONF0_GPIO68 0xCCA8 +#define VF_TAB_PAD_CONF0_GPIO69 0xC828 +#define VF_TAB_PAD_CONF0_GPIO70 0xCCA8 + + + +// +// PAD_CONF1 +// +#define VF_TAB_PAD_CONF1_GPIO0 0x20002 +#define VF_TAB_PAD_CONF1_GPIO1 0x20002 +#define VF_TAB_PAD_CONF1_GPIO2 0x20002 +#define VF_TAB_PAD_CONF1_GPIO3 0x20002 +#define VF_TAB_PAD_CONF1_GPIO4 0x20002 +#define VF_TAB_PAD_CONF1_GPIO5 0x20002 +#define VF_TAB_PAD_CONF1_GPIO6 0x1F000F +#define VF_TAB_PAD_CONF1_GPIO7 0x1F000F +#define VF_TAB_PAD_CONF1_GPIO8 0x1F000F +#define VF_TAB_PAD_CONF1_GPIO9 0x1F000F +#define VF_TAB_PAD_CONF1_GPIO10 0x1F000F +#define VF_TAB_PAD_CONF1_GPIO11 0x1F000F +#define VF_TAB_PAD_CONF1_GPIO12 0x1F000F +#define VF_TAB_PAD_CONF1_GPIO13 0x1F000F +#define VF_TAB_PAD_CONF1_GPIO14 0x20002 +#define VF_TAB_PAD_CONF1_GPIO15 0x20002 +#define VF_TAB_PAD_CONF1_GPIO16 0x20002 +#define VF_TAB_PAD_CONF1_GPIO17 0x20002 +#define VF_TAB_PAD_CONF1_GPIO18 0x20002 +#define VF_TAB_PAD_CONF1_GPIO19 0x20002 +#define VF_TAB_PAD_CONF1_GPIO20 0x20002 +#define VF_TAB_PAD_CONF1_GPIO21 0x20002 +#define VF_TAB_PAD_CONF1_GPIO22 0x20002 +#define VF_TAB_PAD_CONF1_GPIO23 0x20002 +#define VF_TAB_PAD_CONF1_GPIO24 0x00000 +#define VF_TAB_PAD_CONF1_GPIO25 0x00000 +#define VF_TAB_PAD_CONF1_GPIO26 0x00000 +#define VF_TAB_PAD_CONF1_GPIO27 0x00000 +#define VF_TAB_PAD_CONF1_GPIO28 0x00000 +#define VF_TAB_PAD_CONF1_GPIO29 0x00000 +#define VF_TAB_PAD_CONF1_GPIO30 0x00000 +#define VF_TAB_PAD_CONF1_GPIO31 0x20002 +#define VF_TAB_PAD_CONF1_GPIO32 0x00000 +#define VF_TAB_PAD_CONF1_GPIO33 0x00000 +#define VF_TAB_PAD_CONF1_GPIO34 0x00000 +#define VF_TAB_PAD_CONF1_GPIO35 0x00000 +#define VF_TAB_PAD_CONF1_GPIO36 0x00000 +#define VF_TAB_PAD_CONF1_GPIO37 0x00000 +#define VF_TAB_PAD_CONF1_GPIO38 0x00000 +#define VF_TAB_PAD_CONF1_GPIO39 0x00000 +#define VF_TAB_PAD_CONF1_GPIO40 0x00000 +#define VF_TAB_PAD_CONF1_GPIO41 0x00000 +#define VF_TAB_PAD_CONF1_GPIO42 0x00000 +#define VF_TAB_PAD_CONF1_GPIO43 0x00000 +#define VF_TAB_PAD_CONF1_GPIO44 0x00000 +#define VF_TAB_PAD_CONF1_GPIO45 0x00000 +#define VF_TAB_PAD_CONF1_GPIO46 0x00000 +#define VF_TAB_PAD_CONF1_GPIO47 0x00000 +#define VF_TAB_PAD_CONF1_GPIO48 0x00000 +#define VF_TAB_PAD_CONF1_GPIO49 0x00000 +#define VF_TAB_PAD_CONF1_GPIO50 0x00000 +#define VF_TAB_PAD_CONF1_GPIO51 0x00000 +#define VF_TAB_PAD_CONF1_GPIO52 0x00000 +#define VF_TAB_PAD_CONF1_GPIO53 0x00000 +#define VF_TAB_PAD_CONF1_GPIO54 0x20002 +#define VF_TAB_PAD_CONF1_GPIO55 0x00000 +#define VF_TAB_PAD_CONF1_GPIO56 0x20002 +#define VF_TAB_PAD_CONF1_GPIO57 0x00000 +#define VF_TAB_PAD_CONF1_GPIO58 0x00000 +#define VF_TAB_PAD_CONF1_GPIO59 0x00000 +#define VF_TAB_PAD_CONF1_GPIO60 0x00000 +#define VF_TAB_PAD_CONF1_GPIO61 0x00000 +#define VF_TAB_PAD_CONF1_GPIO62 0x00000 +#define VF_TAB_PAD_CONF1_GPIO63 0x00000 +#define VF_TAB_PAD_CONF1_GPIO64 0x00000 +#define VF_TAB_PAD_CONF1_GPIO65 0x20002 +#define VF_TAB_PAD_CONF1_GPIO66 0x20002 +#define VF_TAB_PAD_CONF1_GPIO67 0x20002 +#define VF_TAB_PAD_CONF1_GPIO68 0x20002 +#define VF_TAB_PAD_CONF1_GPIO69 0x20002 +#define VF_TAB_PAD_CONF1_GPIO70 0x20002 + + +// +// PAD_VAL +// +#define VF_TAB_PAD_VAL_GPIO0 0x2 +#define VF_TAB_PAD_VAL_GPIO1 0x2 +#define VF_TAB_PAD_VAL_GPIO2 0x2 +#define VF_TAB_PAD_VAL_GPIO3 0x2 +#define VF_TAB_PAD_VAL_GPIO4 0x2 +#define VF_TAB_PAD_VAL_GPIO5 0x2 +#define VF_TAB_PAD_VAL_GPIO6 0x2 +#define VF_TAB_PAD_VAL_GPIO7 0x2 +#define VF_TAB_PAD_VAL_GPIO8 0x2 +#define VF_TAB_PAD_VAL_GPIO9 0x2 +#define VF_TAB_PAD_VAL_GPIO10 0x2 +#define VF_TAB_PAD_VAL_GPIO11 0x2 +#define VF_TAB_PAD_VAL_GPIO12 0x2 +#define VF_TAB_PAD_VAL_GPIO13 0x2 +#define VF_TAB_PAD_VAL_GPIO14 0x2 +#define VF_TAB_PAD_VAL_GPIO15 0x2 +#define VF_TAB_PAD_VAL_GPIO16 0x4 +#define VF_TAB_PAD_VAL_GPIO17 0x2 +#define VF_TAB_PAD_VAL_GPIO18 0x2 +#define VF_TAB_PAD_VAL_GPIO19 0x2 +#define VF_TAB_PAD_VAL_GPIO20 0x2 +#define VF_TAB_PAD_VAL_GPIO21 0x2 +#define VF_TAB_PAD_VAL_GPIO22 0x2 +#define VF_TAB_PAD_VAL_GPIO23 0x2 +#define VF_TAB_PAD_VAL_GPIO24 0x2 +#define VF_TAB_PAD_VAL_GPIO25 0x2 +#define VF_TAB_PAD_VAL_GPIO26 0x2 +#define VF_TAB_PAD_VAL_GPIO27 0x2 +#define VF_TAB_PAD_VAL_GPIO28 0x2 +#define VF_TAB_PAD_VAL_GPIO29 0x2 +#define VF_TAB_PAD_VAL_GPIO30 0x2 +#define VF_TAB_PAD_VAL_GPIO31 0x2 +#define VF_TAB_PAD_VAL_GPIO32 0x2 +#define VF_TAB_PAD_VAL_GPIO33 0x2 +#define VF_TAB_PAD_VAL_GPIO34 0x2 +#define VF_TAB_PAD_VAL_GPIO35 0x2 +#define VF_TAB_PAD_VAL_GPIO36 0x2 +#define VF_TAB_PAD_VAL_GPIO37 0x2 +#define VF_TAB_PAD_VAL_GPIO38 0x2 +#define VF_TAB_PAD_VAL_GPIO39 0x2 +#define VF_TAB_PAD_VAL_GPIO40 0x2 +#define VF_TAB_PAD_VAL_GPIO41 0x2 +#define VF_TAB_PAD_VAL_GPIO42 0x2 +#define VF_TAB_PAD_VAL_GPIO43 0x2 +#define VF_TAB_PAD_VAL_GPIO44 0x2 +#define VF_TAB_PAD_VAL_GPIO45 0x2 +#define VF_TAB_PAD_VAL_GPIO46 0x2 +#define VF_TAB_PAD_VAL_GPIO47 0x2 +#define VF_TAB_PAD_VAL_GPIO48 0x2 +#define VF_TAB_PAD_VAL_GPIO49 0x2 +#define VF_TAB_PAD_VAL_GPIO50 0x2 +#define VF_TAB_PAD_VAL_GPIO51 0x2 +#define VF_TAB_PAD_VAL_GPIO52 0x2 +#define VF_TAB_PAD_VAL_GPIO53 0x2 +#define VF_TAB_PAD_VAL_GPIO54 0x2 +#define VF_TAB_PAD_VAL_GPIO55 0x2 +#define VF_TAB_PAD_VAL_GPIO56 0x2 +#define VF_TAB_PAD_VAL_GPIO57 0x2 +#define VF_TAB_PAD_VAL_GPIO58 0x2 +#define VF_TAB_PAD_VAL_GPIO59 0x2 +#define VF_TAB_PAD_VAL_GPIO60 0x2 +#define VF_TAB_PAD_VAL_GPIO61 0x4 +#define VF_TAB_PAD_VAL_GPIO62 0x2 +#define VF_TAB_PAD_VAL_GPIO63 0x2 +#define VF_TAB_PAD_VAL_GPIO64 0x2 +#define VF_TAB_PAD_VAL_GPIO65 0x2 +#define VF_TAB_PAD_VAL_GPIO66 0x2 +#define VF_TAB_PAD_VAL_GPIO67 0x0 +#define VF_TAB_PAD_VAL_GPIO68 0x2 +#define VF_TAB_PAD_VAL_GPIO69 0x4 +#define VF_TAB_PAD_VAL_GPIO70 0x2 + + +// +// PAD_DFT +// +#define VF_TAB_PAD_DFT_GPIO0 0xC +#define VF_TAB_PAD_DFT_GPIO1 0xC +#define VF_TAB_PAD_DFT_GPIO2 0xC +#define VF_TAB_PAD_DFT_GPIO3 0xC +#define VF_TAB_PAD_DFT_GPIO4 0xC +#define VF_TAB_PAD_DFT_GPIO5 0xC +#define VF_TAB_PAD_DFT_GPIO6 0xC +#define VF_TAB_PAD_DFT_GPIO7 0xC +#define VF_TAB_PAD_DFT_GPIO8 0xC +#define VF_TAB_PAD_DFT_GPIO9 0xC +#define VF_TAB_PAD_DFT_GPIO10 0xC +#define VF_TAB_PAD_DFT_GPIO11 0xC +#define VF_TAB_PAD_DFT_GPIO12 0xC +#define VF_TAB_PAD_DFT_GPIO13 0xC +#define VF_TAB_PAD_DFT_GPIO14 0xC +#define VF_TAB_PAD_DFT_GPIO15 0xC +#define VF_TAB_PAD_DFT_GPIO16 0xC +#define VF_TAB_PAD_DFT_GPIO17 0xC +#define VF_TAB_PAD_DFT_GPIO18 0xC +#define VF_TAB_PAD_DFT_GPIO19 0xC +#define VF_TAB_PAD_DFT_GPIO20 0xC +#define VF_TAB_PAD_DFT_GPIO21 0xC +#define VF_TAB_PAD_DFT_GPIO22 0xC +#define VF_TAB_PAD_DFT_GPIO23 0xC +#define VF_TAB_PAD_DFT_GPIO24 0xC +#define VF_TAB_PAD_DFT_GPIO25 0xC +#define VF_TAB_PAD_DFT_GPIO26 0xC +#define VF_TAB_PAD_DFT_GPIO27 0xC +#define VF_TAB_PAD_DFT_GPIO28 0xC +#define VF_TAB_PAD_DFT_GPIO29 0xC +#define VF_TAB_PAD_DFT_GPIO30 0xC +#define VF_TAB_PAD_DFT_GPIO31 0xC +#define VF_TAB_PAD_DFT_GPIO32 0xC +#define VF_TAB_PAD_DFT_GPIO33 0xC +#define VF_TAB_PAD_DFT_GPIO34 0xC +#define VF_TAB_PAD_DFT_GPIO35 0xC +#define VF_TAB_PAD_DFT_GPIO36 0xC +#define VF_TAB_PAD_DFT_GPIO37 0xC +#define VF_TAB_PAD_DFT_GPIO38 0xC +#define VF_TAB_PAD_DFT_GPIO39 0xC +#define VF_TAB_PAD_DFT_GPIO40 0xC +#define VF_TAB_PAD_DFT_GPIO41 0xC +#define VF_TAB_PAD_DFT_GPIO42 0xC +#define VF_TAB_PAD_DFT_GPIO43 0xC +#define VF_TAB_PAD_DFT_GPIO44 0xC +#define VF_TAB_PAD_DFT_GPIO45 0xC +#define VF_TAB_PAD_DFT_GPIO46 0xC +#define VF_TAB_PAD_DFT_GPIO47 0xC +#define VF_TAB_PAD_DFT_GPIO48 0xC +#define VF_TAB_PAD_DFT_GPIO49 0xC +#define VF_TAB_PAD_DFT_GPIO50 0xC +#define VF_TAB_PAD_DFT_GPIO51 0xC +#define VF_TAB_PAD_DFT_GPIO52 0xC +#define VF_TAB_PAD_DFT_GPIO53 0xC +#define VF_TAB_PAD_DFT_GPIO54 0xC +#define VF_TAB_PAD_DFT_GPIO55 0xC +#define VF_TAB_PAD_DFT_GPIO56 0xC +#define VF_TAB_PAD_DFT_GPIO57 0xC +#define VF_TAB_PAD_DFT_GPIO58 0xC +#define VF_TAB_PAD_DFT_GPIO59 0xC +#define VF_TAB_PAD_DFT_GPIO60 0xC +#define VF_TAB_PAD_DFT_GPIO61 0xC +#define VF_TAB_PAD_DFT_GPIO62 0xC +#define VF_TAB_PAD_DFT_GPIO63 0xC +#define VF_TAB_PAD_DFT_GPIO64 0xC +#define VF_TAB_PAD_DFT_GPIO65 0xC +#define VF_TAB_PAD_DFT_GPIO66 0xC +#define VF_TAB_PAD_DFT_GPIO67 0xC +#define VF_TAB_PAD_DFT_GPIO68 0xC +#define VF_TAB_PAD_DFT_GPIO69 0xC +#define VF_TAB_PAD_DFT_GPIO70 0xC + + +// +//SUS WELL +// + +// +// CONF0 +// +#define VF_TAB_PAD_CONF0_GPIO_SUS0 0xCCA8 +#define VF_TAB_PAD_CONF0_GPIO_SUS1 0xCCA8 +#define VF_TAB_PAD_CONF0_GPIO_SUS2 0xCCA8 +#define VF_TAB_PAD_CONF0_GPIO_SUS3 0xCD28 +#define VF_TAB_PAD_CONF0_GPIO_SUS4 0xCD28 +#define VF_TAB_PAD_CONF0_GPIO_SUS5 0xCD28 +#define VF_TAB_PAD_CONF0_GPIO_SUS6 0x8850 +#define VF_TAB_PAD_CONF0_GPIO_SUS7 0x8850 +#define VF_TAB_PAD_CONF0_GPIO_SUS8 0xCCA8 +#define VF_TAB_PAD_CONF0_GPIO_SUS9 0xCCA8 +#define VF_TAB_PAD_CONF0_GPIO_SUS10 0xCCA8 +#define VF_TAB_PAD_CONF0_GPIO_SUS11 0xC828 +#define VF_TAB_PAD_CONF0_GPIO_SUS12 0xC828 +#define VF_TAB_PAD_CONF0_GPIO_SUS13 0xCCA8 +#define VF_TAB_PAD_CONF0_GPIO_SUS14 0xCCA8 +#define VF_TAB_PAD_CONF0_GPIO_SUS15 0x8C80 +#define VF_TAB_PAD_CONF0_GPIO_SUS16 0xC828 + +// +// CONF1 +// +#define VF_TAB_PAD_CONF1_GPIO_SUS0 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS1 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS2 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS3 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS4 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS5 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS6 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS7 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS8 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS9 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS10 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS11 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS12 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS13 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS14 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS15 0 +#define VF_TAB_PAD_CONF1_GPIO_SUS16 0 + +// +// PAD_VAL +// +#define VF_TAB_PAD_VAL_GPIO_SUS0 0 +#define VF_TAB_PAD_VAL_GPIO_SUS1 0 +#define VF_TAB_PAD_VAL_GPIO_SUS2 0 +#define VF_TAB_PAD_VAL_GPIO_SUS3 0 +#define VF_TAB_PAD_VAL_GPIO_SUS4 0 +#define VF_TAB_PAD_VAL_GPIO_SUS5 0 +#define VF_TAB_PAD_VAL_GPIO_SUS6 0 +#define VF_TAB_PAD_VAL_GPIO_SUS7 0 +#define VF_TAB_PAD_VAL_GPIO_SUS8 0 +#define VF_TAB_PAD_VAL_GPIO_SUS9 0 +#define VF_TAB_PAD_VAL_GPIO_SUS10 0 +#define VF_TAB_PAD_VAL_GPIO_SUS11 0 +#define VF_TAB_PAD_VAL_GPIO_SUS12 0 +#define VF_TAB_PAD_VAL_GPIO_SUS13 0 +#define VF_TAB_PAD_VAL_GPIO_SUS14 0 +#define VF_TAB_PAD_VAL_GPIO_SUS15 0 +#define VF_TAB_PAD_VAL_GPIO_SUS16 0 + +// +// PAD_DFT +// +#define VF_TAB_PAD_DFT_GPIO_SUS0 0 +#define VF_TAB_PAD_DFT_GPIO_SUS1 0 +#define VF_TAB_PAD_DFT_GPIO_SUS2 0 +#define VF_TAB_PAD_DFT_GPIO_SUS3 0 +#define VF_TAB_PAD_DFT_GPIO_SUS4 0 +#define VF_TAB_PAD_DFT_GPIO_SUS5 0 +#define VF_TAB_PAD_DFT_GPIO_SUS6 0 +#define VF_TAB_PAD_DFT_GPIO_SUS7 0 +#define VF_TAB_PAD_DFT_GPIO_SUS8 0 +#define VF_TAB_PAD_DFT_GPIO_SUS9 0 +#define VF_TAB_PAD_DFT_GPIO_SUS10 0 +#define VF_TAB_PAD_DFT_GPIO_SUS11 0 +#define VF_TAB_PAD_DFT_GPIO_SUS12 0 +#define VF_TAB_PAD_DFT_GPIO_SUS13 0 +#define VF_TAB_PAD_DFT_GPIO_SUS14 0 +#define VF_TAB_PAD_DFT_GPIO_SUS15 0 +#define VF_TAB_PAD_DFT_GPIO_SUS16 0 + + +// +// +// GPIO Register Settings for ValleyFalls (Netbook) +// +// +// IO Space configyuration registers +// Field Descriptions: +// USE: Defines the pin's usage model: GPIO (G) or Native (N) mode. +// I/O: Defines whether GPIOs are inputs (I) or outputs (O). +// (Note: Only meaningful for pins used as GPIOs.) +// LVL: This field gives you the initial value for "output" GPIO's. +// (Note: The output level is dependent upon whether the pin is inverted.) +// TPE: Defines whether Trigger Positive Edge Enable. +// TNE: Defines whether Trigger Negative Edge Enable. +// WAKE_EN: only support in SUS community +// (Note: Only affects the level sent to the GPE logic and does not +// affect the level read through the GPIO registers.) +// +// +// Memory spcae configuration registers +// +// Field Descriptions: +// PAD releated: +// PAD_CONF0 +// PAD_CONF1 +// PAD_VAL +// PAD_DFT +// +// Notes: +// 1. N = Native , G = GPIO , I = Input, O = Output, - = BOTH/NOT SURE +// +// Signal UsedAs USE I/O LVL TPE TNE PCONF0 PCONF1 PVAL PDFT +// ------------------------------------------------------------------------------------------------------------------------- +// GPIO0 UART1_RXD-L N I - - - cd29h - - - +// GPIO1 UART1_TXD-0 N O - - - cd29h - - - +// *GPIO2 UART1_RTS_B-1 N I - - - cca9h - - - +// *GPIO3 UART1_CTS_B-H N O - - - cca9h - - - + +// GPIO4 NMI_B-H G - - - - cca9h - - - +// GPIO5 GPIO_D5 G - - - - cca9h - - - +// GPIO6 GPIO_D6 G O - - - 8d51h - - - +// GPIO7 GPIO_D7 G O - - - 8cd1h - - - +// GPIO8 GPIO_D8 G O - - - 8cd1h - - - +// GPIO9 GPIO_D9 G I - - - 8cd1h - - - + +// GPIO10 GPIO_D10 G O - - - 8d51h - - - +// GPIO11 GPIO_D11 G O - - - 8cd1h - - - +// GPIO12 GPIO_D12 G O - - - 8cd1h - - - +// GPIO13 GPIO_D13 G I - - - 8d51h - - - + +// GPIO14 SATA_GP0 N - - - - - - - - +// GPIO15 SATA_GP1-L N - - - - ccaah - - - + +// GPIO16 SATA_LEDN-OD-O N O - - - - - - - +// GPIO17 PCIE_CLKREQ0B-20K,H N I - - - cd2ah - - - +// GPIO18 PCIE_CLKREQ1B-20K,H N O - - - ccaah - - - +// GPIO19 PCIE_CLKREQ2B-20K,H N I - - - ccaah - - - +// GPIO20 PCIE_CLKREQ3B-20K,H N - - - - ccaah - - - +// GPIO21 PCIE_CLKREQ4B-20K,H N - - - - - - - - +// GPIO22 FLEX_CLK_SE0-20K,L N O - - - ccaah - - - +// GPIO23 FLEX_CLK_SE1-20K,L N - - - - - - - - + +// GPIO24 HDA_RSTB N O - - - 8d02h - - - +// GPIO25 HDA_SYNC N O - - - 8d02h - - - +// GPIO26 HDA_CLK N O - - - 8d02h - - - +// GPIO27 HDA_SDO N I - - - 8d02h - - - +// GPIO28 HDA_SDI0 N I - - - - - - - +// GPIO29 HDA_SDI1 N O - - - - - - - +// GPIO30 HDA_DOCKRSTB N I - - - - - - - +// GPIO31 HDA_DOCKENB N O - - - - - - - + +// GPIO32 SDMMC1_CLK N - - - - 208d51h - - - +// GPIO33 SDMMC1_D0 N - - - - 8cd1h - - - +// GPIO34 SDMMC1_D1 N - - - - 8cd1h - - - +// GPIO35 SDMMC1_D2 N - - - - 8cd1h - - - +// GPIO36 SDMMC1_D3_CD_B N - - - - 8cd1h - - - +// GPIO37 MMC1_D4_SD_WE N - - - - 8cd1h - - - +// GPIO38 MMC1_D5 N - - - - 8cd1h - - - +// GPIO39 MMC1_D6 N - - - - 8cd1h - - - +// GPIO40 MMC1_D7 N - - - - 8cd1h - - - +// GPIO41 SDMMC1_CMD N - - - - 8cd1h - - - +// GPIO42 MMC1_RESET_B N - - - - 208d51h - - - + +// GPIO43 SDMMC2_CLK N - - - - 208d51h - - - +// GPIO44 SDMMC2_D0 N - - - - 8cd1h - - - +// GPIO45 SDMMC2_D1 N - - - - 8cd1h - - - +// GPIO46 SDMMC2_D2 N - - - - 8cd1h - - - +// GPIO47 SDMMC2_D3_CD_B N - - - - 8cd1h - - - +// GPIO48 SDMMC2_CMD N - - - - 8cd1h - - - + +// GPIO49 SDMMC3_CLK N - - - - 8d51h - - - +// GPIO50 SDMMC3_D0 N - - - - 8cd1h - - - +// GPIO51 SDMMC3_D1 N - - - - 8cd1h - - - +// GPIO52 SDMMC3_D2 N - - - - 8cd1h - - - +// GPIO53 SDMMC3_D3 N - - - - 8cd1h - - - +// GPIO54 SDMMC3_CD_B N - - - - cca9h - - - +// GPIO55 SDMMC3_CMD N - - - - 8cd1h - - - +// GPIO56 SDMMC3_1P8_EN N - - - - cd29h - - - + +// GPIO57 LPC_AD0 N - - - - - - - - +// GPIO58 LPC_AD1 N - - - - - - - - +// GPIO59 LPC_AD2 N - - - - - - - - +// GPIO60 LPC_AD3 N - - - - - - - - +// GPIO61 LPC_FRAMEB N O - - - - - - - +// GPIO62 LPC_CLKOUT0 N O - - - - - - - +// GPIO63 LPC_CLKOUT1 N O - - - - - - - +// GPIO64 LPC_CLKRUNB N - - - - - - - - + +// GPIO65 SMB_DATA N - - - - - - - - +// GPIO66 SMB_CLK N - - - - - - - - +// GPIO67 SMB_ALERTB N - - - - - - - - + +// GPIO68 ILB_SEIRQ N - - - - - - - - +// GPIO69 SPKR N O - - - - - - - + +//SUS WELL + + +//GPIO_SUS0 GPIO_SUS0 N O - - - CCA8h - - - +//GPIO_SUS1 GPIO_SUS1 N O - - - CCA8h - - - +//GPIO_SUS2 GPIO_SUS2 N O - - - CCA8h - - - +//GPIO_SUS3 GPIO_SUS3 N O - - - CD28h - - - +//GPIO_SUS4 GPIO_SUS4 N O - - - CD28h - - - +//GPIO_SUS5 GPIO_SUS5 N O - - - CD28h - - - +//GPIO_SUS6 SUSPWRDNACK-0 N O - - - 8850h - - - +//GPIO_SUS7 PMU_SLP_DDRVTT_B-0 N O - - - 8850h - - - +//GPIO_SUS8 PMU_WAKE_B-20K,H N O - - - CCA8h - - - +//GPIO_SUS9 PMU_PWRBTN_B-20K,H N O - - - CCA8h - - - +//GPIO_SUS10 PMU_WAKE_LAN_B-20K,H N O - - - CCA8h - - - +//GPIO_SUS11 SUS_STAT_B-1 N O - - - C828h - - - +//GPIO_SUS12 PMU_SUSCLK-0 N O - - - C828h - - - +//GPIO_SUS13 USB_OC0_B-20K,H N O - - - CCA8h - - - +//GPIO_SUS14 USB_OC1_B-20K,H N O - - - CCA8h - - - +//GPIO_SUS15 SPI_CS1_B-20K,H N O - - - 8C80h - - - +//GPIO_SUS16 SPI_CS1_B-20K,H N O - - - C828h - - - +// + +#define VF_NET_GPIO_USE_SEL_VAL_0_31 0x00000000 +#define VF_NET_GPIO_USE_SEL_VAL_32_63 0x00000000 +#define VF_NET_GPIO_USE_SEL_VAL_64_70 0x00000000 +#define VF_NET_GPIO_USE_SEL_VAL_SUS 0x00000000 + +// +//1010 --00 0100 01-- 0101 --0- 0001 1010 +// +#define VF_NET_GPIO_IO_SEL_VAL_0_31 0x00000000 // BIT30 | BIT28 | BIT27 | BIT19 | BIT17 | BIT13 | BIT9 | BIT2 | BIT0 +#define VF_NET_GPIO_IO_SEL_VAL_32_63 0x00000000 +#define VF_NET_GPIO_IO_SEL_VAL_64_70 0x00000000 +#define VF_NET_GPIO_IO_SEL_VAL_SUS 0x00000000 + + +#define VF_NET_GPIO_LVL_VAL_0_31 0x00000000 +#define VF_NET_GPIO_LVL_VAL_32_63 0x00000000 +#define VF_NET_GPIO_LVL_VAL_64_70 0x00000000 +#define VF_NET_GPIO_LVL_VAL_SUS 0x00000000 + +#define VF_NET_GPIO_TPE_VAL_0_31 0x00000000 +#define VF_NET_GPIO_TPE_VAL_SUS 0x00000000 + +#define VF_NET_GPIO_TNE_VAL_0_31 0x00000000 +#define VF_NET_GPIO_TNE_VAL_SUS 0x00000000 + +#define VF_NET_GPIO_TS_VAL_0_31 0x00000000 +#define VF_NET_GPIO_TS_VAL_SUS 0x00000000 + + +// +// Memory space registers +// + + +// +// CONF0 +// +#define VF_NET_PAD_CONF0_GPIO0 0xcd29 +#define VF_NET_PAD_CONF0_GPIO1 0xcd29 +#define VF_NET_PAD_CONF0_GPIO2 0xcca9 +#define VF_NET_PAD_CONF0_GPIO3 0xcca9 +#define VF_NET_PAD_CONF0_GPIO4 0xcca8 +#define VF_NET_PAD_CONF0_GPIO5 0xcca8 +#define VF_NET_PAD_CONF0_GPIO6 0x8d50 +#define VF_NET_PAD_CONF0_GPIO7 0x8cd0 +#define VF_NET_PAD_CONF0_GPIO8 0x8cd0 +#define VF_NET_PAD_CONF0_GPIO9 0x8cd0 +#define VF_NET_PAD_CONF0_GPIO10 0x8d50 +#define VF_NET_PAD_CONF0_GPIO11 0x8cd0 +#define VF_NET_PAD_CONF0_GPIO12 0x8cd0 +#define VF_NET_PAD_CONF0_GPIO13 0x8d50 +#define VF_NET_PAD_CONF0_GPIO14 0xCCA8 +#define VF_NET_PAD_CONF0_GPIO15 0xccaa +#define VF_NET_PAD_CONF0_GPIO16 0xC828 +#define VF_NET_PAD_CONF0_GPIO17 0xcd2a +#define VF_NET_PAD_CONF0_GPIO18 0xccaa +#define VF_NET_PAD_CONF0_GPIO19 0xccaa +#define VF_NET_PAD_CONF0_GPIO20 0xccaa +#define VF_NET_PAD_CONF0_GPIO21 0xCCA9 +#define VF_NET_PAD_CONF0_GPIO22 0xccaa +#define VF_NET_PAD_CONF0_GPIO23 0xCD2A +#define VF_NET_PAD_CONF0_GPIO24 0x8d02 +#define VF_NET_PAD_CONF0_GPIO25 0x8d02 +#define VF_NET_PAD_CONF0_GPIO26 0x8d02 +#define VF_NET_PAD_CONF0_GPIO27 0x8d02 +#define VF_NET_PAD_CONF0_GPIO28 0x8D02 +#define VF_NET_PAD_CONF0_GPIO29 0x8D02 +#define VF_NET_PAD_CONF0_GPIO30 0x8D00 +#define VF_NET_PAD_CONF0_GPIO31 0xCD2A +#define VF_NET_PAD_CONF0_GPIO32 0x208d51 +#define VF_NET_PAD_CONF0_GPIO33 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO34 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO35 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO36 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO37 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO38 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO39 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO40 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO41 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO42 0x208d51 +#define VF_NET_PAD_CONF0_GPIO43 0x208d51 +#define VF_NET_PAD_CONF0_GPIO44 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO45 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO46 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO47 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO48 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO49 0x8d51 +#define VF_NET_PAD_CONF0_GPIO50 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO51 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO52 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO53 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO54 0xcca9 +#define VF_NET_PAD_CONF0_GPIO55 0x8cd1 +#define VF_NET_PAD_CONF0_GPIO56 0xcd29 +#define VF_NET_PAD_CONF0_GPIO57 0x8C80 +#define VF_NET_PAD_CONF0_GPIO58 0x8C80 +#define VF_NET_PAD_CONF0_GPIO59 0x8C80 +#define VF_NET_PAD_CONF0_GPIO60 0x8C80 +#define VF_NET_PAD_CONF0_GPIO61 0x8800 +#define VF_NET_PAD_CONF0_GPIO62 0x8D00 +#define VF_NET_PAD_CONF0_GPIO63 0x8800 +#define VF_NET_PAD_CONF0_GPIO64 0x8800 +#define VF_NET_PAD_CONF0_GPIO65 0xC828 +#define VF_NET_PAD_CONF0_GPIO66 0xC828 +#define VF_NET_PAD_CONF0_GPIO67 0xC828 +#define VF_NET_PAD_CONF0_GPIO68 0xCCA8 +#define VF_NET_PAD_CONF0_GPIO69 0xC828 +#define VF_NET_PAD_CONF0_GPIO70 0xCCA8 + + + + +// +// PAD_CONF1 +// +#define VF_NET_PAD_CONF1_GPIO0 0x20002 +#define VF_NET_PAD_CONF1_GPIO1 0x20002 +#define VF_NET_PAD_CONF1_GPIO2 0x20002 +#define VF_NET_PAD_CONF1_GPIO3 0x20002 +#define VF_NET_PAD_CONF1_GPIO4 0x20002 +#define VF_NET_PAD_CONF1_GPIO5 0x20002 +#define VF_NET_PAD_CONF1_GPIO6 0x1F000F +#define VF_NET_PAD_CONF1_GPIO7 0x1F000F +#define VF_NET_PAD_CONF1_GPIO8 0x1F000F +#define VF_NET_PAD_CONF1_GPIO9 0x1F000F +#define VF_NET_PAD_CONF1_GPIO10 0x1F000F +#define VF_NET_PAD_CONF1_GPIO11 0x1F000F +#define VF_NET_PAD_CONF1_GPIO12 0x1F000F +#define VF_NET_PAD_CONF1_GPIO13 0x1F000F +#define VF_NET_PAD_CONF1_GPIO14 0x20002 +#define VF_NET_PAD_CONF1_GPIO15 0x20002 +#define VF_NET_PAD_CONF1_GPIO16 0x20002 +#define VF_NET_PAD_CONF1_GPIO17 0x20002 +#define VF_NET_PAD_CONF1_GPIO18 0x20002 +#define VF_NET_PAD_CONF1_GPIO19 0x20002 +#define VF_NET_PAD_CONF1_GPIO20 0x20002 +#define VF_NET_PAD_CONF1_GPIO21 0x20002 +#define VF_NET_PAD_CONF1_GPIO22 0x20002 +#define VF_NET_PAD_CONF1_GPIO23 0x20002 +#define VF_NET_PAD_CONF1_GPIO24 0x00000 +#define VF_NET_PAD_CONF1_GPIO25 0x00000 +#define VF_NET_PAD_CONF1_GPIO26 0x00000 +#define VF_NET_PAD_CONF1_GPIO27 0x00000 +#define VF_NET_PAD_CONF1_GPIO28 0x00000 +#define VF_NET_PAD_CONF1_GPIO29 0x00000 +#define VF_NET_PAD_CONF1_GPIO30 0x00000 +#define VF_NET_PAD_CONF1_GPIO31 0x20002 +#define VF_NET_PAD_CONF1_GPIO32 0x00000 +#define VF_NET_PAD_CONF1_GPIO33 0x00000 +#define VF_NET_PAD_CONF1_GPIO34 0x00000 +#define VF_NET_PAD_CONF1_GPIO35 0x00000 +#define VF_NET_PAD_CONF1_GPIO36 0x00000 +#define VF_NET_PAD_CONF1_GPIO37 0x00000 +#define VF_NET_PAD_CONF1_GPIO38 0x00000 +#define VF_NET_PAD_CONF1_GPIO39 0x00000 +#define VF_NET_PAD_CONF1_GPIO40 0x00000 +#define VF_NET_PAD_CONF1_GPIO41 0x00000 +#define VF_NET_PAD_CONF1_GPIO42 0x00000 +#define VF_NET_PAD_CONF1_GPIO43 0x00000 +#define VF_NET_PAD_CONF1_GPIO44 0x00000 +#define VF_NET_PAD_CONF1_GPIO45 0x00000 +#define VF_NET_PAD_CONF1_GPIO46 0x00000 +#define VF_NET_PAD_CONF1_GPIO47 0x00000 +#define VF_NET_PAD_CONF1_GPIO48 0x00000 +#define VF_NET_PAD_CONF1_GPIO49 0x00000 +#define VF_NET_PAD_CONF1_GPIO50 0x00000 +#define VF_NET_PAD_CONF1_GPIO51 0x00000 +#define VF_NET_PAD_CONF1_GPIO52 0x00000 +#define VF_NET_PAD_CONF1_GPIO53 0x00000 +#define VF_NET_PAD_CONF1_GPIO54 0x20002 +#define VF_NET_PAD_CONF1_GPIO55 0x00000 +#define VF_NET_PAD_CONF1_GPIO56 0x20002 +#define VF_NET_PAD_CONF1_GPIO57 0x00000 +#define VF_NET_PAD_CONF1_GPIO58 0x00000 +#define VF_NET_PAD_CONF1_GPIO59 0x00000 +#define VF_NET_PAD_CONF1_GPIO60 0x00000 +#define VF_NET_PAD_CONF1_GPIO61 0x00000 +#define VF_NET_PAD_CONF1_GPIO62 0x00000 +#define VF_NET_PAD_CONF1_GPIO63 0x00000 +#define VF_NET_PAD_CONF1_GPIO64 0x00000 +#define VF_NET_PAD_CONF1_GPIO65 0x20002 +#define VF_NET_PAD_CONF1_GPIO66 0x20002 +#define VF_NET_PAD_CONF1_GPIO67 0x20002 +#define VF_NET_PAD_CONF1_GPIO68 0x20002 +#define VF_NET_PAD_CONF1_GPIO69 0x20002 +#define VF_NET_PAD_CONF1_GPIO70 0x20002 + + + +// +// PAD_VAL +// +#define VF_NET_PAD_VAL_GPIO0 0x2 +#define VF_NET_PAD_VAL_GPIO1 0x2 +#define VF_NET_PAD_VAL_GPIO2 0x2 +#define VF_NET_PAD_VAL_GPIO3 0x2 +#define VF_NET_PAD_VAL_GPIO4 0x2 +#define VF_NET_PAD_VAL_GPIO5 0x2 +#define VF_NET_PAD_VAL_GPIO6 0x2 +#define VF_NET_PAD_VAL_GPIO7 0x2 +#define VF_NET_PAD_VAL_GPIO8 0x2 +#define VF_NET_PAD_VAL_GPIO9 0x2 +#define VF_NET_PAD_VAL_GPIO10 0x2 +#define VF_NET_PAD_VAL_GPIO11 0x2 +#define VF_NET_PAD_VAL_GPIO12 0x2 +#define VF_NET_PAD_VAL_GPIO13 0x2 +#define VF_NET_PAD_VAL_GPIO14 0x2 +#define VF_NET_PAD_VAL_GPIO15 0x2 +#define VF_NET_PAD_VAL_GPIO16 0x4 +#define VF_NET_PAD_VAL_GPIO17 0x2 +#define VF_NET_PAD_VAL_GPIO18 0x2 +#define VF_NET_PAD_VAL_GPIO19 0x2 +#define VF_NET_PAD_VAL_GPIO20 0x2 +#define VF_NET_PAD_VAL_GPIO21 0x2 +#define VF_NET_PAD_VAL_GPIO22 0x2 +#define VF_NET_PAD_VAL_GPIO23 0x2 +#define VF_NET_PAD_VAL_GPIO24 0x2 +#define VF_NET_PAD_VAL_GPIO25 0x2 +#define VF_NET_PAD_VAL_GPIO26 0x2 +#define VF_NET_PAD_VAL_GPIO27 0x2 +#define VF_NET_PAD_VAL_GPIO28 0x2 +#define VF_NET_PAD_VAL_GPIO29 0x2 +#define VF_NET_PAD_VAL_GPIO30 0x2 +#define VF_NET_PAD_VAL_GPIO31 0x2 +#define VF_NET_PAD_VAL_GPIO32 0x2 +#define VF_NET_PAD_VAL_GPIO33 0x2 +#define VF_NET_PAD_VAL_GPIO34 0x2 +#define VF_NET_PAD_VAL_GPIO35 0x2 +#define VF_NET_PAD_VAL_GPIO36 0x2 +#define VF_NET_PAD_VAL_GPIO37 0x2 +#define VF_NET_PAD_VAL_GPIO38 0x2 +#define VF_NET_PAD_VAL_GPIO39 0x2 +#define VF_NET_PAD_VAL_GPIO40 0x2 +#define VF_NET_PAD_VAL_GPIO41 0x2 +#define VF_NET_PAD_VAL_GPIO42 0x2 +#define VF_NET_PAD_VAL_GPIO43 0x2 +#define VF_NET_PAD_VAL_GPIO44 0x2 +#define VF_NET_PAD_VAL_GPIO45 0x2 +#define VF_NET_PAD_VAL_GPIO46 0x2 +#define VF_NET_PAD_VAL_GPIO47 0x2 +#define VF_NET_PAD_VAL_GPIO48 0x2 +#define VF_NET_PAD_VAL_GPIO49 0x2 +#define VF_NET_PAD_VAL_GPIO50 0x2 +#define VF_NET_PAD_VAL_GPIO51 0x2 +#define VF_NET_PAD_VAL_GPIO52 0x2 +#define VF_NET_PAD_VAL_GPIO53 0x2 +#define VF_NET_PAD_VAL_GPIO54 0x2 +#define VF_NET_PAD_VAL_GPIO55 0x2 +#define VF_NET_PAD_VAL_GPIO56 0x2 +#define VF_NET_PAD_VAL_GPIO57 0x2 +#define VF_NET_PAD_VAL_GPIO58 0x2 +#define VF_NET_PAD_VAL_GPIO59 0x2 +#define VF_NET_PAD_VAL_GPIO60 0x2 +#define VF_NET_PAD_VAL_GPIO61 0x4 +#define VF_NET_PAD_VAL_GPIO62 0x2 +#define VF_NET_PAD_VAL_GPIO63 0x2 +#define VF_NET_PAD_VAL_GPIO64 0x2 +#define VF_NET_PAD_VAL_GPIO65 0x2 +#define VF_NET_PAD_VAL_GPIO66 0x2 +#define VF_NET_PAD_VAL_GPIO67 0x0 +#define VF_NET_PAD_VAL_GPIO68 0x2 +#define VF_NET_PAD_VAL_GPIO69 0x4 +#define VF_NET_PAD_VAL_GPIO70 0x2 + + +// +// PAD_DFT +// +#define VF_NET_PAD_DFT_GPIO0 0xC +#define VF_NET_PAD_DFT_GPIO1 0xC +#define VF_NET_PAD_DFT_GPIO2 0xC +#define VF_NET_PAD_DFT_GPIO3 0xC +#define VF_NET_PAD_DFT_GPIO4 0xC +#define VF_NET_PAD_DFT_GPIO5 0xC +#define VF_NET_PAD_DFT_GPIO6 0xC +#define VF_NET_PAD_DFT_GPIO7 0xC +#define VF_NET_PAD_DFT_GPIO8 0xC +#define VF_NET_PAD_DFT_GPIO9 0xC +#define VF_NET_PAD_DFT_GPIO10 0xC +#define VF_NET_PAD_DFT_GPIO11 0xC +#define VF_NET_PAD_DFT_GPIO12 0xC +#define VF_NET_PAD_DFT_GPIO13 0xC +#define VF_NET_PAD_DFT_GPIO14 0xC +#define VF_NET_PAD_DFT_GPIO15 0xC +#define VF_NET_PAD_DFT_GPIO16 0xC +#define VF_NET_PAD_DFT_GPIO17 0xC +#define VF_NET_PAD_DFT_GPIO18 0xC +#define VF_NET_PAD_DFT_GPIO19 0xC +#define VF_NET_PAD_DFT_GPIO20 0xC +#define VF_NET_PAD_DFT_GPIO21 0xC +#define VF_NET_PAD_DFT_GPIO22 0xC +#define VF_NET_PAD_DFT_GPIO23 0xC +#define VF_NET_PAD_DFT_GPIO24 0xC +#define VF_NET_PAD_DFT_GPIO25 0xC +#define VF_NET_PAD_DFT_GPIO26 0xC +#define VF_NET_PAD_DFT_GPIO27 0xC +#define VF_NET_PAD_DFT_GPIO28 0xC +#define VF_NET_PAD_DFT_GPIO29 0xC +#define VF_NET_PAD_DFT_GPIO30 0xC +#define VF_NET_PAD_DFT_GPIO31 0xC +#define VF_NET_PAD_DFT_GPIO32 0xC +#define VF_NET_PAD_DFT_GPIO33 0xC +#define VF_NET_PAD_DFT_GPIO34 0xC +#define VF_NET_PAD_DFT_GPIO35 0xC +#define VF_NET_PAD_DFT_GPIO36 0xC +#define VF_NET_PAD_DFT_GPIO37 0xC +#define VF_NET_PAD_DFT_GPIO38 0xC +#define VF_NET_PAD_DFT_GPIO39 0xC +#define VF_NET_PAD_DFT_GPIO40 0xC +#define VF_NET_PAD_DFT_GPIO41 0xC +#define VF_NET_PAD_DFT_GPIO42 0xC +#define VF_NET_PAD_DFT_GPIO43 0xC +#define VF_NET_PAD_DFT_GPIO44 0xC +#define VF_NET_PAD_DFT_GPIO45 0xC +#define VF_NET_PAD_DFT_GPIO46 0xC +#define VF_NET_PAD_DFT_GPIO47 0xC +#define VF_NET_PAD_DFT_GPIO48 0xC +#define VF_NET_PAD_DFT_GPIO49 0xC +#define VF_NET_PAD_DFT_GPIO50 0xC +#define VF_NET_PAD_DFT_GPIO51 0xC +#define VF_NET_PAD_DFT_GPIO52 0xC +#define VF_NET_PAD_DFT_GPIO53 0xC +#define VF_NET_PAD_DFT_GPIO54 0xC +#define VF_NET_PAD_DFT_GPIO55 0xC +#define VF_NET_PAD_DFT_GPIO56 0xC +#define VF_NET_PAD_DFT_GPIO57 0xC +#define VF_NET_PAD_DFT_GPIO58 0xC +#define VF_NET_PAD_DFT_GPIO59 0xC +#define VF_NET_PAD_DFT_GPIO60 0xC +#define VF_NET_PAD_DFT_GPIO61 0xC +#define VF_NET_PAD_DFT_GPIO62 0xC +#define VF_NET_PAD_DFT_GPIO63 0xC +#define VF_NET_PAD_DFT_GPIO64 0xC +#define VF_NET_PAD_DFT_GPIO65 0xC +#define VF_NET_PAD_DFT_GPIO66 0xC +#define VF_NET_PAD_DFT_GPIO67 0xC +#define VF_NET_PAD_DFT_GPIO68 0xC +#define VF_NET_PAD_DFT_GPIO69 0xC +#define VF_NET_PAD_DFT_GPIO70 0xC + +// +// PCONF0 +// +#define VF_NET_PAD_CONF0_GPIO_SUS0 0xCCA8 +#define VF_NET_PAD_CONF0_GPIO_SUS1 0xCCA8 +#define VF_NET_PAD_CONF0_GPIO_SUS2 0xCCA8 +#define VF_NET_PAD_CONF0_GPIO_SUS3 0xCD28 +#define VF_NET_PAD_CONF0_GPIO_SUS4 0xCD28 +#define VF_NET_PAD_CONF0_GPIO_SUS5 0xCD28 +#define VF_NET_PAD_CONF0_GPIO_SUS6 0x8850 +#define VF_NET_PAD_CONF0_GPIO_SUS7 0x8850 +#define VF_NET_PAD_CONF0_GPIO_SUS8 0xCCA8 +#define VF_NET_PAD_CONF0_GPIO_SUS9 0xCCA8 +#define VF_NET_PAD_CONF0_GPIO_SUS10 0xCCA8 +#define VF_NET_PAD_CONF0_GPIO_SUS11 0xC828 +#define VF_NET_PAD_CONF0_GPIO_SUS12 0xC828 +#define VF_NET_PAD_CONF0_GPIO_SUS13 0xCCA8 +#define VF_NET_PAD_CONF0_GPIO_SUS14 0xCCA8 +#define VF_NET_PAD_CONF0_GPIO_SUS15 0x8C80 +#define VF_NET_PAD_CONF0_GPIO_SUS16 0xC828 + +// +// PCONF1 +// +#define VF_NET_PAD_CONF1_GPIO_SUS0 0 +#define VF_NET_PAD_CONF1_GPIO_SUS1 0 +#define VF_NET_PAD_CONF1_GPIO_SUS2 0 +#define VF_NET_PAD_CONF1_GPIO_SUS3 0 +#define VF_NET_PAD_CONF1_GPIO_SUS4 0 +#define VF_NET_PAD_CONF1_GPIO_SUS5 0 +#define VF_NET_PAD_CONF1_GPIO_SUS6 0 +#define VF_NET_PAD_CONF1_GPIO_SUS7 0 +#define VF_NET_PAD_CONF1_GPIO_SUS8 0 +#define VF_NET_PAD_CONF1_GPIO_SUS9 0 +#define VF_NET_PAD_CONF1_GPIO_SUS10 0 +#define VF_NET_PAD_CONF1_GPIO_SUS11 0 +#define VF_NET_PAD_CONF1_GPIO_SUS12 0 +#define VF_NET_PAD_CONF1_GPIO_SUS13 0 +#define VF_NET_PAD_CONF1_GPIO_SUS14 0 +#define VF_NET_PAD_CONF1_GPIO_SUS15 0 +#define VF_NET_PAD_CONF1_GPIO_SUS16 0 + + +#define VF_NET_PAD_VAL_GPIO_SUS0 0 +#define VF_NET_PAD_VAL_GPIO_SUS1 0 +#define VF_NET_PAD_VAL_GPIO_SUS2 0 +#define VF_NET_PAD_VAL_GPIO_SUS3 0 +#define VF_NET_PAD_VAL_GPIO_SUS4 0 +#define VF_NET_PAD_VAL_GPIO_SUS5 0 +#define VF_NET_PAD_VAL_GPIO_SUS6 0 +#define VF_NET_PAD_VAL_GPIO_SUS7 0 +#define VF_NET_PAD_VAL_GPIO_SUS8 0 +#define VF_NET_PAD_VAL_GPIO_SUS9 0 +#define VF_NET_PAD_VAL_GPIO_SUS10 0 +#define VF_NET_PAD_VAL_GPIO_SUS11 0 +#define VF_NET_PAD_VAL_GPIO_SUS12 0 +#define VF_NET_PAD_VAL_GPIO_SUS13 0 +#define VF_NET_PAD_VAL_GPIO_SUS14 0 +#define VF_NET_PAD_VAL_GPIO_SUS15 0 +#define VF_NET_PAD_VAL_GPIO_SUS16 0 + + +#define VF_NET_PAD_DFT_GPIO_SUS0 0 +#define VF_NET_PAD_DFT_GPIO_SUS1 0 +#define VF_NET_PAD_DFT_GPIO_SUS2 0 +#define VF_NET_PAD_DFT_GPIO_SUS3 0 +#define VF_NET_PAD_DFT_GPIO_SUS4 0 +#define VF_NET_PAD_DFT_GPIO_SUS5 0 +#define VF_NET_PAD_DFT_GPIO_SUS6 0 +#define VF_NET_PAD_DFT_GPIO_SUS7 0 +#define VF_NET_PAD_DFT_GPIO_SUS8 0 +#define VF_NET_PAD_DFT_GPIO_SUS9 0 +#define VF_NET_PAD_DFT_GPIO_SUS10 0 +#define VF_NET_PAD_DFT_GPIO_SUS11 0 +#define VF_NET_PAD_DFT_GPIO_SUS12 0 +#define VF_NET_PAD_DFT_GPIO_SUS13 0 +#define VF_NET_PAD_DFT_GPIO_SUS14 0 +#define VF_NET_PAD_DFT_GPIO_SUS15 0 +#define VF_NET_PAD_DFT_GPIO_SUS16 0 + + +// +// Function Prototypes +// +EFI_STATUS +PlatformPchInit ( + IN SYSTEM_CONFIGURATION *SystemConfiguration, + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 PlatformType + ); + +EFI_STATUS +PlatformCpuInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN SYSTEM_CONFIGURATION *SystemConfiguration, + IN EFI_PLATFORM_CPU_INFO *PlatformCpuInfo + ); + +EFI_STATUS +PeimInitializeFlashMap ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +PeimInstallFlashMapPpi ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +EFIAPI +IchReset ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +; + +BOOLEAN +GetSleepTypeAfterWakeup ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT16 *SleepType + ); + +EFI_STATUS +EFIAPI +GetWakeupEventAndSaveToHob ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +; + +EFI_STATUS +EFIAPI +MemoryDiscoveredPpiNotifyCallback ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +; + +EFI_STATUS +EFIAPI +PeiGetVariable ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CHAR16 *VariableName, + IN EFI_GUID * VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +; + +EFI_STATUS +EFIAPI +PeiGetNextVariableName ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ) +; + +EFI_STATUS +UpdateBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ); + +EFI_STATUS +EFIAPI +EndOfPeiPpiNotifyCallback ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +EFI_STATUS +EFIAPI +PeimInitializeRecovery ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +; + +VOID +CheckPowerOffNow ( + VOID + ); + +VOID +IchGpioInit ( + IN UINT16 PlatformType, + IN SYSTEM_CONFIGURATION *SystemConfiguration + ); + +EFI_STATUS +PcieSecondaryBusReset ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT8 Bus, + IN UINT8 Dev, + IN UINT8 Fun + ); + +VOID +SetPlatformBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ); + +BOOLEAN +CheckIfJumperSetForRecovery( + VOID + ); + +EFI_STATUS +EFIAPI +FindFv ( + IN EFI_PEI_FIND_FV_PPI *This, + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT UINT8 *FvNumber, + OUT EFI_FIRMWARE_VOLUME_HEADER **FVAddress + ); + +BOOLEAN +IsA16Inverted ( + ); + +EFI_STATUS +EFIAPI +CpuOnlyReset ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +EFIAPI +InitLan ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN SYSTEM_CONFIGURATION *Buffer + ); + +EFI_STATUS +EFIAPI +Stall ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_STALL_PPI *This, + IN UINTN Microseconds + ); + +EFI_STATUS +MultiPlatformInfoInit ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ); + +BOOLEAN +IsRecoveryJumper ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob +); + +EFI_STATUS +CheckOsSelection ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN SYSTEM_CONFIGURATION *SystemConfiguration + ); + +EFI_STATUS +PlatformInfoUpdate ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob, + IN SYSTEM_CONFIGURATION *SystemConfiguration + ); + +VOID +PlatformSsaInit ( +IN SYSTEM_CONFIGURATION *SystemConfiguration, +IN CONST EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +InitializePlatform ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob, + IN SYSTEM_CONFIGURATION *SystemConfiguration +); + +VOID +MchInit ( +IN CONST EFI_PEI_SERVICES **PeiServices + ); + + +EFI_STATUS +EFIAPI +SetPeiCacheMode ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +EFIAPI +SetDxeCacheMode ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +GPIO_initialization ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *SmbusPpi + ); + + +BOOLEAN +IsRtcUipAlwaysSet ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + + + +EFI_STATUS +InitPchUsb ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +EFIAPI +PublishMemoryTypeInfo ( + void + ); + + +#endif diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/PlatformInfoInit.c b/Vlv2TbltDevicePkg/PlatformInitPei/PlatformInfoInit.c new file mode 100644 index 0000000000..48d69a3a59 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/PlatformInfoInit.c @@ -0,0 +1,186 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + PlatformInfoInit.c + +Abstract: + Platform Info Driver. + +--*/ + +#include "PlatformEarlyInit.h" + +#define LEN_64M 0x4000000 + +// +// Default PCI32 resource size +// +#define RES_MEM32_MIN_LEN 0x38000000 + +#define RES_IO_BASE 0x0D00 +#define RES_IO_LIMIT 0xFFFF + +#define MemoryCeilingVariable L"MemCeil." + +EFI_STATUS +CheckOsSelection ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN SYSTEM_CONFIGURATION *SystemConfiguration + ) +{ + EFI_STATUS Status; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; + UINTN VariableSize; + EFI_OS_SELECTION_HOB *OsSelectionHob; + UINT8 OsSelection; + UINT8 *LpssDataHobPtr; + UINT8 *LpssDataVarPtr; + UINTN i; + + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&Variable + ); + if (!EFI_ERROR(Status)) { + VariableSize = sizeof (OsSelection); + Status = Variable->GetVariable ( + Variable, + L"OsSelection", + &gOsSelectionVariableGuid, + NULL, + &VariableSize, + &OsSelection + ); + + if (!EFI_ERROR(Status) && (SystemConfiguration->ReservedO != OsSelection)) { + // + // Build HOB for OsSelection + // + OsSelectionHob = BuildGuidHob (&gOsSelectionVariableGuid, sizeof (EFI_OS_SELECTION_HOB)); + ASSERT (OsSelectionHob != NULL); + + OsSelectionHob->OsSelectionChanged = TRUE; + OsSelectionHob->OsSelection = OsSelection; + SystemConfiguration->ReservedO = OsSelectionHob->OsSelection; + + // + // Load LPSS and SCC defalut configurations + // + OsSelectionHob->LpssData.LpsseMMCEnabled = FALSE; + OsSelectionHob->LpssData.LpssSdioEnabled = TRUE; + OsSelectionHob->LpssData.LpssSdcardEnabled = TRUE; + OsSelectionHob->LpssData.LpssSdCardSDR25Enabled = FALSE; + OsSelectionHob->LpssData.LpssSdCardDDR50Enabled = TRUE; + OsSelectionHob->LpssData.LpssMipiHsi = FALSE; + OsSelectionHob->LpssData.LpsseMMC45Enabled = TRUE; + OsSelectionHob->LpssData.LpsseMMC45DDR50Enabled = TRUE; + OsSelectionHob->LpssData.LpsseMMC45HS200Enabled = FALSE; + OsSelectionHob->LpssData.LpsseMMC45RetuneTimerValue = 8; + OsSelectionHob->LpssData.eMMCBootMode = 1; // Auto Detect + + + SystemConfiguration->Lpe = OsSelectionHob->Lpe; + SystemConfiguration->PchAzalia = SystemConfiguration->PchAzalia; + LpssDataHobPtr = &OsSelectionHob->LpssData.LpssPciModeEnabled; + LpssDataVarPtr = &SystemConfiguration->LpssPciModeEnabled; + + for (i = 0; i < sizeof(EFI_PLATFORM_LPSS_DATA); i++) { + *LpssDataVarPtr = *LpssDataHobPtr; + LpssDataVarPtr++; + LpssDataHobPtr++; + } + } + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +PlatformInfoUpdate ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob, + IN SYSTEM_CONFIGURATION *SystemConfiguration + ) +{ + EFI_STATUS Status; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; + UINTN VariableSize; + UINT32 MemoryCeiling; + + // + // Checking PCI32 resource from previous boot to determine the memory ceiling + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&Variable + ); + if (!EFI_ERROR(Status)) { + // + // Get the memory ceiling + // + VariableSize = sizeof(MemoryCeiling); + Status = Variable->GetVariable ( + Variable, + MemoryCeilingVariable, + &gEfiGlobalVariableGuid, + NULL, + &VariableSize, + &MemoryCeiling + ); + if(!EFI_ERROR(Status)) { + // + // Set the new PCI32 resource Base if the variable available + // + PlatformInfoHob->PciData.PciResourceMem32Base = MemoryCeiling; + PlatformInfoHob->MemData.MemMaxTolm = MemoryCeiling; + PlatformInfoHob->MemData.MemTolm = MemoryCeiling; + + // + // Platform PCI MMIO Size in unit of 1MB + // + PlatformInfoHob->MemData.MmioSize = 0x1000 - (UINT16)(PlatformInfoHob->MemData.MemMaxTolm >> 20); + } + } + + return EFI_SUCCESS; +} + +/** + Initialize the platform related info hob according to the + pre-determine value or setup option + + @retval EFI_SUCCESS Memory initialization completed successfully. + @retval Others All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +InitializePlatform ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob, + IN SYSTEM_CONFIGURATION *SystemConfiguration +) +{ +// +// -- cchew10 need to update here. +// + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/PlatformInitPei.inf b/Vlv2TbltDevicePkg/PlatformInitPei/PlatformInitPei.inf new file mode 100644 index 0000000000..fc517ef6f3 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/PlatformInitPei.inf @@ -0,0 +1,122 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# Module Name: +# +# PlatformEarlyInit.inf +# +# Abstract: +# +# Component description file for PlatformEarlyInit module +# +#--*/ + +[defines] +INF_VERSION = 0x00010005 +BASE_NAME = PlatformEarlyInit +FILE_GUID = 0A5EA2E1-BE0B-44a0-A775-F429C9A018A0 +MODULE_TYPE = PEIM +VERSION_STRING = 1.0 +PI_SPECIFICATION_VERSION = 0x0001000A +ENTRY_POINT = PlatformEarlyInitEntry + +[sources.common] + BootMode.c + CpuInitPeim.c + PchInitPeim.c + MchInit.c + MemoryCallback.c + MemoryPeim.c + PlatformEarlyInit.c + PlatformEarlyInit.h + PlatformInfoInit.c + LegacySpeaker.c + LegacySpeaker.h + Stall.c + PlatformSsaInitPeim.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + IA32FamilyCpuPkg/IA32FamilyCpuPkg.dec + UefiCpuPkg/UefiCpuPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + PeimEntryPoint + DebugLib + HobLib + IoLib +# PeiKscLib + MultiPlatformLib + PcdLib + PchPlatformLib + MtrrLib + +[Ppis] + gEfiPeiStallPpiGuid + gPeiSpeakerInterfacePpiGuid + gEfiPeiMemoryDiscoveredPpiGuid + gVlvPolicyPpiGuid + gEfiPeiReadOnlyVariable2PpiGuid + gEfiPeiResetPpiGuid + gEfiEndOfPeiSignalPpiGuid + gPeiSmbusPolicyPpiGuid + gEfiFindFvPpiGuid + gPeiCapsulePpiGuid + gEfiPeiBootInRecoveryModePpiGuid + gEfiPeiRecoveryModulePpiGuid + gEfiPeiDeviceRecoveryModulePpiGuid + gPeiCachePpiGuid + gEfiPeiMasterBootModePpiGuid + gEfiPeiSmbusPpiGuid + gPchInitPpiGuid + gPchUsbPolicyPpiGuid + +[Guids] + gEfiSetupVariableGuid + gEfiPlatformInfoGuid + gEfiPlatformBootModeGuid + gEfiPlatformCpuInfoGuid + gEfiGlobalVariableGuid + gRecoveryOnFatFloppyDiskGuid + gRecoveryOnFatUsbDiskGuid + gRecoveryOnFatIdeDiskGuid + gRecoveryOnDataCdGuid + gMfgModeVariableGuid + gEfiNormalSetupGuid + gEfiMemoryTypeInformationGuid + gOsSelectionVariableGuid + +[Pcd.common] + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainBase + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainSize + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + gEfiIchTokenSpaceGuid.PcdPeiIchEhciControllerMemoryBaseAddress + + gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress + gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Base + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Size + +[Pcd] + gEfiVLVTokenSpaceGuid.PcdMeasuredBootEnable + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState + +[Depex] + gEfiPeiReadOnlyVariable2PpiGuid AND gPeiCachePpiGuid diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/PlatformSsaInitPeim.c b/Vlv2TbltDevicePkg/PlatformInitPei/PlatformSsaInitPeim.c new file mode 100644 index 0000000000..c2cffb8be8 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/PlatformSsaInitPeim.c @@ -0,0 +1,63 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + PlatformSsaInitPeim.c + +Abstract: + + +--*/ + +#include "PlatformEarlyInit.h" + +/** + Perform SSA related platform initialization. + +**/ +VOID +PlatformSsaInit ( + IN SYSTEM_CONFIGURATION *SystemConfiguration, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + + DEBUG ((EFI_D_ERROR, "PlatformSsaInit() - Start\n")); + DEBUG ((EFI_D_ERROR, "PlatformSsaInit() - SystemConfiguration->ISPDevSel 0x%x\n",SystemConfiguration->ISPDevSel)); + if(SystemConfiguration->ISPDevSel == 0x02) + { + // + // Device 3 Interrupt Route + // + MmioWrite16 ( + (ILB_BASE_ADDRESS + R_PCH_ILB_D3IR), + V_PCH_ILB_DXXIR_IAR_PIRQH // For IUNIT + ); + MmioRead16(ILB_BASE_ADDRESS + R_PCH_ILB_D3IR); // Read Posted Writes Register + DEBUG ((EFI_D_ERROR, "PlatformSsaInit() - Device 3 Interrupt Route Done\n")); + } + + // + // Device 2 Interrupt Route + // + MmioWrite16 ( + (ILB_BASE_ADDRESS + R_PCH_ILB_D2IR), + V_PCH_ILB_DXXIR_IAR_PIRQA // For IGD + ); + MmioRead16(ILB_BASE_ADDRESS + R_PCH_ILB_D2IR); // Read Posted Writes Register + DEBUG ((EFI_D_ERROR, "PlatformSsaInit() - Device 2 Interrupt Route Done\n")); + + return; +} diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/Recovery.c b/Vlv2TbltDevicePkg/PlatformInitPei/Recovery.c new file mode 100644 index 0000000000..a29d8c5481 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/Recovery.c @@ -0,0 +1,366 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + Recovery.c + +Abstract: + + Tiano PEIM to provide the platform recovery functionality. + +--*/ + +#include "PlatformEarlyInit.h" + +#define PEI_FVMAIN_COMPACT_GUID \ + {0x4A538818, 0x5AE0, 0x4eb2, 0xB2, 0xEB, 0x48, 0x8b, 0x23, 0x65, 0x70, 0x22}; + +EFI_GUID FvMainCompactFileGuid = PEI_FVMAIN_COMPACT_GUID; + +// +// Required Service +// +EFI_STATUS +EFIAPI +PlatformRecoveryModule ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_MODULE_PPI *This + ); + +// +// Module globals +// + +typedef struct { + EFI_GUID CapsuleGuid; + UINT32 HeaderSize; + UINT32 Flags; + UINT32 CapsuleImageSize; + UINT32 SequenceNumber; + EFI_GUID InstanceId; + UINT32 OffsetToSplitInformation; + UINT32 OffsetToCapsuleBody; + UINT32 OffsetToOemDefinedHeader; + UINT32 OffsetToAuthorInformation; + UINT32 OffsetToRevisionInformation; + UINT32 OffsetToShortDescription; + UINT32 OffsetToLongDescription; + UINT32 OffsetToApplicableDevices; +} OLD_EFI_CAPSULE_HEADER; + + +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 +}; + +/** + Provide the functionality of the Recovery Module. + + @param PeiServices General purpose services available to every PEIM. + + @retval Status EFI_SUCCESS if the interface could be successfully + installed + +**/ +EFI_STATUS +EFIAPI +PeimInitializeRecovery ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + Status = (*PeiServices)->InstallPpi ( + PeiServices, + &mRecoveryPpiList + ); + + return Status; +} + +/** + Provide the functionality of the Ea Recovery Module. + + @param PeiServices General purpose services available to every PEIM. + @param This Pointer to PEI_RECOVERY_MODULE_INTERFACE. + + @retval EFI_SUCCESS If the interface could be successfully + installed. + @retval EFI_UNSUPPORTED Not supported. + +**/ +EFI_STATUS +EFIAPI +PlatformRecoveryModule ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_MODULE_PPI *This + ) +{ + 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; + OLD_EFI_CAPSULE_HEADER *CapsuleHeader; + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS HobOld; + EFI_HOB_CAPSULE_VOLUME *CapsuleHob; + BOOLEAN HobUpdate; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + UINTN Index; + BOOLEAN FoundFvMain; + BOOLEAN FoundCapsule; + static EFI_GUID mEfiCapsuleHeaderGuid = EFI_CAPSULE_GUID; + EFI_PEI_STALL_PPI *StallPpi; + + (*PeiServices)->ReportStatusCode ( + PeiServices, + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_PC_RECOVERY_BEGIN, + 0, + NULL, + NULL + ); + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiPeiStallPpiGuid, + 0, + NULL, + &StallPpi + ); + ASSERT_EFI_ERROR (Status); + + StallPpi->Stall( + PeiServices, + StallPpi, + 5000000 + ); + + + Index = 0; + + Status = EFI_SUCCESS; + HobUpdate = FALSE; + + ProviderAvailable = TRUE; + ImageFound = FALSE; + NumberOfImageProviders = 0; + + DeviceRecoveryModule = NULL; + + FoundCapsule = FALSE; + FoundFvMain = FALSE; + + DEBUG ((EFI_D_ERROR | 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 == TRUE) { + + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiDeviceRecoveryModulePpiGuid, + Index, + NULL, + &DeviceRecoveryModule + ); + + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Device Recovery PPI located\n")); + NumberOfImageProviders++; + + Status = DeviceRecoveryModule->GetNumberRecoveryCapsules ( + (EFI_PEI_SERVICES**)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; + } + } + + // + // If there is an image provider, get the capsule ID + // + if (ProviderAvailable) { + RecoveryCapsuleSize = 0; + + Status = DeviceRecoveryModule->GetRecoveryCapsuleInfo ( + (EFI_PEI_SERVICES**)PeiServices, + DeviceRecoveryModule, + 0, + &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, &gRecoveryOnFatIdeDiskGuid)) && + (!CompareGuid (&DeviceId, &gRecoveryOnFatFloppyDiskGuid)) && + (!CompareGuid (&DeviceId, &gRecoveryOnDataCdGuid)) && + (!CompareGuid (&DeviceId, &gRecoveryOnFatUsbDiskGuid)) + ) { + return EFI_UNSUPPORTED; + } + + Buffer = NULL; + Status = (*PeiServices)->AllocatePages ( + PeiServices, + EfiBootServicesCode, + (RecoveryCapsuleSize - 1) / 0x1000 + 1, + &Address + ); + + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "AllocatePage Returns: %r\n", Status)); + + if (EFI_ERROR(Status)) { + return Status; + } + + Buffer = (UINT8 *) (UINTN) Address; + + (*PeiServices)->ReportStatusCode ( + PeiServices, + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_PC_CAPSULE_LOAD, + 0, + NULL, + NULL + ); + + Status = DeviceRecoveryModule->LoadRecoveryCapsule ( + (EFI_PEI_SERVICES**)PeiServices, + DeviceRecoveryModule, + 0, + Buffer + ); + + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "LoadRecoveryCapsule Returns: %r\n", Status)); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Update FV Hob if found + // + Status = (*PeiServices)->GetHobList (PeiServices, &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)); + // + // BUGBUG Why is it a FV hob if it is greater than 0x50000? + // + if (Hob.FirmwareVolume->Length > 0x50000) { + 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); + } + + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Buffer; + CapsuleHeader = (OLD_EFI_CAPSULE_HEADER *)Buffer; + + // + // Check if top of file is a capsule + // + if (CompareGuid ((EFI_GUID *)CapsuleHeader, &mEfiCapsuleHeaderGuid)) { + FoundCapsule = TRUE; + } else if (FvHeader->Signature == EFI_FVH_SIGNATURE) { + // + // Assume the Firmware volume is a "FVMAIN" image + // + FoundFvMain = TRUE; + } + + if (FoundFvMain) { + // + // 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)FvHeader, + FvHeader->FvLength + ); + } + } + + if (FoundCapsule) { + // + // Build capsule hob + // + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_CV, + sizeof (EFI_HOB_CAPSULE_VOLUME), + &CapsuleHob + ); + if (EFI_ERROR (Status)) { + return Status; + } + CapsuleHob->BaseAddress = (UINT64)((UINTN)CapsuleHeader + (UINTN)CapsuleHeader->OffsetToCapsuleBody); + CapsuleHob->Length = (UINT64)((UINTN)CapsuleHeader->CapsuleImageSize -(UINTN)CapsuleHeader->OffsetToCapsuleBody); + (*PeiServices)->ReportStatusCode ( + PeiServices, + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_PC_CAPSULE_START, + 0, + NULL, + NULL + ); + } + } + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Recovery Module Returning: %r\n", Status)); + return Status; +} diff --git a/Vlv2TbltDevicePkg/PlatformInitPei/Stall.c b/Vlv2TbltDevicePkg/PlatformInitPei/Stall.c new file mode 100644 index 0000000000..46df63aed7 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformInitPei/Stall.c @@ -0,0 +1,96 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +Module Name: + + Stall.c + +Abstract: + + Produce Stall Ppi. + +--*/ + + +#include "PlatformEarlyInit.h" + + +/** + + Waits for at least the given number of microseconds. + + @param PeiServices General purpose services available to every PEIM. + @param This PPI instance structure. + @param Microseconds Desired length of time to wait. + + @retval EFI_SUCCESS If the desired amount of time was passed. + +*/ +EFI_STATUS +EFIAPI +Stall ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_STALL_PPI *This, + IN UINTN Microseconds + ) +{ + UINTN Ticks; + UINTN Counts; + UINT32 CurrentTick; + UINT32 OriginalTick; + UINT32 RemainingTick; + + if (Microseconds == 0) { + return EFI_SUCCESS; + } + + OriginalTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR); + OriginalTick &= (V_PCH_ACPI_PM1_TMR_MAX_VAL - 1); + CurrentTick = OriginalTick; + + // + // The timer frequency is 3.579545MHz, so 1 ms corresponds to 3.58 clocks + // + Ticks = Microseconds * 358 / 100 + OriginalTick + 1; + + // + // The loops needed for timer overflow + // + Counts = (UINTN)RShiftU64((UINT64)Ticks, 24); + + // + // Remaining clocks within one loop + // + RemainingTick = Ticks & 0xFFFFFF; + + // + // Do not intend to use TMROF_STS bit of register PM1_STS, because this add extra + // one I/O operation, and may generate SMI + // + while (Counts != 0) { + CurrentTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR) & B_PCH_ACPI_PM1_TMR_VAL; + if (CurrentTick <= OriginalTick) { + Counts--; + } + OriginalTick = CurrentTick; + } + + while ((RemainingTick > CurrentTick) && (OriginalTick <= CurrentTick)) { + OriginalTick = CurrentTick; + CurrentTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR) & B_PCH_ACPI_PM1_TMR_VAL; + } + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/PlatformPei/BootMode.c b/Vlv2TbltDevicePkg/PlatformPei/BootMode.c new file mode 100644 index 0000000000..4d933a09db --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/BootMode.c @@ -0,0 +1,403 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + BootMode.c + +Abstract: + + EFI PEIM to provide the platform support functionality on the Thurley. + + +--*/ +#include "CommonHeader.h" +#include "Platform.h" +#include "PlatformBaseAddresses.h" +#include "PchAccess.h" +#include "PlatformBootMode.h" +#include + +#include + +// +// Priority of our boot modes, highest priority first +// +EFI_BOOT_MODE mBootModePriority[] = { + BOOT_IN_RECOVERY_MODE, + BOOT_WITH_DEFAULT_SETTINGS, + BOOT_ON_FLASH_UPDATE, + BOOT_ON_S2_RESUME, + BOOT_ON_S3_RESUME, + BOOT_ON_S4_RESUME, + BOOT_WITH_MINIMAL_CONFIGURATION, + BOOT_ASSUMING_NO_CONFIGURATION_CHANGES, + BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS, + BOOT_WITH_FULL_CONFIGURATION, + BOOT_ON_S5_RESUME +}; + +EFI_PEI_NOTIFY_DESCRIPTOR mCapsuleNotifyList[1] = { + { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiCapsulePpiGuid, + CapsulePpiNotifyCallback + } +}; + +BOOLEAN +GetSleepTypeAfterWakeup ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT16 *SleepType + ); + +EFI_STATUS +EFIAPI +CapsulePpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + PEI_CAPSULE_PPI *Capsule; + + Status = (*PeiServices)->GetBootMode((const EFI_PEI_SERVICES **)PeiServices, &BootMode); + ASSERT_EFI_ERROR (Status); + + if (BootMode == BOOT_ON_S3_RESUME) { + // + // Determine if we're in capsule update mode + // + Status = (*PeiServices)->LocatePpi ((const EFI_PEI_SERVICES **)PeiServices, + &gPeiCapsulePpiGuid, + 0, + NULL, + (VOID **)&Capsule + ); + + if (Status == EFI_SUCCESS) { + if (Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES**)PeiServices) == EFI_SUCCESS) { + BootMode = BOOT_ON_FLASH_UPDATE; + Status = (*PeiServices)->SetBootMode((const EFI_PEI_SERVICES **)PeiServices, BootMode); + ASSERT_EFI_ERROR (Status); + } + } + } + + return Status; +} + +/** + Check CMOS register bit to determine if previous boot was successful + + @param PeiServices pointer to the PEI Service Table + + @retval TRUE - Previous Boot was success + @retval FALSE - Previous Boot wasn't success + +**/ +BOOLEAN +IsPreviousBootSuccessful( + IN CONST EFI_PEI_SERVICES **PeiServices + + ) +{ + EFI_STATUS Status; + BOOLEAN BootState; + UINTN DataSize; + CHAR16 VarName[] = BOOT_STATE_VARIABLE_NAME; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiVar; + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&PeiVar + ); + ASSERT_EFI_ERROR (Status); + + // + // Get last Boot State Variable to confirm that it is not a first boot . + // + + DataSize = sizeof (BOOLEAN); + Status = PeiVar->GetVariable ( + PeiVar, + VarName, + &gEfiBootStateGuid, + NULL, + &DataSize, + &BootState + ); + if (EFI_ERROR (Status) || (BootState == TRUE)) { + return FALSE; + } + + DEBUG ((EFI_D_INFO, "Previous boot cycle successfully completed handover to OS\n")); + return TRUE; +} +#ifdef NOCS_S3_SUPPORT +EFI_STATUS +UpdateBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + UINT16 SleepType; + CHAR16 *strBootMode; + + Status = (*PeiServices)->GetBootMode(PeiServices, &BootMode); + ASSERT_EFI_ERROR (Status); + if (BootMode == BOOT_IN_RECOVERY_MODE){ + return Status; + } + + // + // Let's assume things are OK if not told otherwise + // + BootMode = BOOT_WITH_FULL_CONFIGURATION; + + if (GetSleepTypeAfterWakeup (PeiServices, &SleepType)) { + switch (SleepType) { + case V_PCH_ACPI_PM1_CNT_S3: + BootMode = BOOT_ON_S3_RESUME; + Status = (*PeiServices)->NotifyPpi (PeiServices, &mCapsuleNotifyList[0]); + ASSERT_EFI_ERROR (Status); + break; + + case V_PCH_ACPI_PM1_CNT_S4: + BootMode = BOOT_ON_S4_RESUME; + break; + + case V_PCH_ACPI_PM1_CNT_S5: + BootMode = BOOT_ON_S5_RESUME; + break; + } // switch (SleepType) + } + + if (IsFastBootEnabled (PeiServices) && IsPreviousBootSuccessful (PeiServices)) { + DEBUG ((EFI_D_INFO, "Prioritizing Boot mode to BOOT_WITH_MINIMAL_CONFIGURATION\n")); + PrioritizeBootMode (&BootMode, BOOT_WITH_MINIMAL_CONFIGURATION); + } + + switch (BootMode) { + case BOOT_WITH_FULL_CONFIGURATION: + strBootMode = L"BOOT_WITH_FULL_CONFIGURATION"; + break; + case BOOT_WITH_MINIMAL_CONFIGURATION: + strBootMode = L"BOOT_WITH_MINIMAL_CONFIGURATION"; + break; + case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES: + strBootMode = L"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES"; + break; + case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS: + strBootMode = L"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS"; + break; + case BOOT_WITH_DEFAULT_SETTINGS: + strBootMode = L"BOOT_WITH_DEFAULT_SETTINGS"; + break; + case BOOT_ON_S4_RESUME: + strBootMode = L"BOOT_ON_S4_RESUME"; + break; + case BOOT_ON_S5_RESUME: + strBootMode = L"BOOT_ON_S5_RESUME"; + break; + case BOOT_ON_S2_RESUME: + strBootMode = L"BOOT_ON_S2_RESUME"; + break; + case BOOT_ON_S3_RESUME: + strBootMode = L"BOOT_ON_S3_RESUME"; + + break; + case BOOT_ON_FLASH_UPDATE: + strBootMode = L"BOOT_ON_FLASH_UPDATE"; + break; + case BOOT_IN_RECOVERY_MODE: + strBootMode = L"BOOT_IN_RECOVERY_MODE"; + break; + default: + strBootMode = L"Unknown boot mode"; + } // switch (BootMode) + + DEBUG ((EFI_D_ERROR, "Setting BootMode to %s\n", strBootMode)); + Status = (*PeiServices)->SetBootMode(PeiServices, BootMode); + ASSERT_EFI_ERROR (Status); + + return Status; +} +#endif + +/** + Get sleep type after wakeup + + @param PeiServices Pointer to the PEI Service Table. + @param SleepType Sleep type to be returned. + + @retval TRUE A wake event occured without power failure. + @retval FALSE Power failure occured or not a wakeup. + +**/ +BOOLEAN +GetSleepTypeAfterWakeup ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT16 *SleepType + ) +{ + UINT16 Pm1Sts; + UINT16 Pm1Cnt; + UINT16 GenPmCon1; + // + // VLV BIOS Specification 0.6.2 - Section 18.4, "Power Failure Consideration" + // + // When the SUS_PWR_FLR bit is set, it indicates the SUS well power is lost. + // This bit is in the SUS Well and defaults to 1’b1 based on RSMRST# assertion (not cleared by any type of reset). + // System BIOS should follow cold boot path if SUS_PWR_FLR (PBASE + 0x20[14]), + // GEN_RST_STS (PBASE + 0x20[9]) or PWRBTNOR_STS (ABASE + 0x00[11]) is set to 1’b1 + // regardless of the value in the SLP_TYP (ABASE + 0x04[12:10]) field. + // + GenPmCon1 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1); + + // + // Read the ACPI registers + // + Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS); + Pm1Cnt = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT); + + if ((GenPmCon1 & (B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR | B_PCH_PMC_GEN_PMCON_GEN_RST_STS)) || + (Pm1Sts & B_PCH_ACPI_PM1_STS_PRBTNOR)) { + // + // If power failure indicator, then don't attempt s3 resume. + // Clear PM1_CNT of S3 and set it to S5 as we just had a power failure, and memory has + // lost already. This is to make sure no one will use PM1_CNT to check for S3 after + // power failure. + // + if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) { + Pm1Cnt = ((Pm1Cnt & ~B_PCH_ACPI_PM1_CNT_SLP_TYP) | V_PCH_ACPI_PM1_CNT_S5); + IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, Pm1Cnt); + } + // + // Clear Wake Status (WAK_STS) + // + } + // + // Get sleep type if a wake event occurred and there is no power failure + // + if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) { + *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP; + return TRUE; + } else if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S4) { + *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP; + return TRUE; + } + return FALSE; +} + +BOOLEAN +EFIAPI +IsFastBootEnabled ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiReadOnlyVarPpi; + UINTN VarSize; + SYSTEM_CONFIGURATION SystemConfiguration; + BOOLEAN FastBootEnabledStatus; + + FastBootEnabledStatus = FALSE; + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&PeiReadOnlyVarPpi + ); + if (Status == EFI_SUCCESS) { + VarSize = sizeof (SYSTEM_CONFIGURATION); + Status = PeiReadOnlyVarPpi->GetVariable ( + PeiReadOnlyVarPpi, + PLATFORM_SETUP_VARIABLE_NAME, + &gEfiSetupVariableGuid, + NULL, + &VarSize, + &SystemConfiguration + ); + if (Status == EFI_SUCCESS) { + if (SystemConfiguration.FastBoot != 0) { + FastBootEnabledStatus = TRUE; + } + } + } + + return FastBootEnabledStatus; +} + +/** + Given the current boot mode, and a proposed new boot mode, determine + which has priority. If the new boot mode has higher priority, then + make it the current boot mode. + + @param CurrentBootMode pointer to current planned boot mode + @param NewBootMode proposed boot mode + + @retval EFI_NOT_FOUND if either boot mode is not recognized + @retval EFI_SUCCESS if both boot mode values were recognized and + were processed. +**/ +EFI_STATUS +PrioritizeBootMode ( + IN OUT EFI_BOOT_MODE *CurrentBootMode, + IN EFI_BOOT_MODE NewBootMode + ) +{ + UINT32 CurrentIndex; + UINT32 NewIndex; + + // + // Find the position of the current boot mode in our priority array + // + for ( CurrentIndex = 0; + CurrentIndex < sizeof (mBootModePriority) / sizeof (mBootModePriority[0]); + CurrentIndex++) { + if (mBootModePriority[CurrentIndex] == *CurrentBootMode) { + break; + } + } + if (CurrentIndex >= sizeof (mBootModePriority) / sizeof (mBootModePriority[0])) { + return EFI_NOT_FOUND; + } + + // + // Find the position of the new boot mode in our priority array + // + for ( NewIndex = 0; + NewIndex < sizeof (mBootModePriority) / sizeof (mBootModePriority[0]); + NewIndex++) { + if (mBootModePriority[NewIndex] == NewBootMode) { + // + // If this new boot mode occurs before the current boot mode in the + // priority array, then take it. + // + if (NewIndex < CurrentIndex) { + *CurrentBootMode = NewBootMode; + } + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} diff --git a/Vlv2TbltDevicePkg/PlatformPei/CommonHeader.h b/Vlv2TbltDevicePkg/PlatformPei/CommonHeader.h new file mode 100644 index 0000000000..19e26acdcf --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/CommonHeader.h @@ -0,0 +1,65 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#endif diff --git a/Vlv2TbltDevicePkg/PlatformPei/MemoryCallback.c b/Vlv2TbltDevicePkg/PlatformPei/MemoryCallback.c new file mode 100644 index 0000000000..82954d3a50 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/MemoryCallback.c @@ -0,0 +1,160 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + 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 + + +**/ + + +#include "CommonHeader.h" +#include "Platform.h" +#include +#include +#include +#include "VlvAccess.h" + + +EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode[] = { +{ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiBootInRecoveryModePpiGuid, + NULL +} +}; + +#if 0 +STATIC +EFI_STATUS +GetMemorySize ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT64 *LowMemoryLength, + OUT UINT64 *HighMemoryLength + ) +{ + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS Hob; + + *HighMemoryLength = 0; + *LowMemoryLength = 0x100000; + // + // Get the HOB list for processing + // + Status = (*PeiServices)->GetHobList (PeiServices, (void **)&Hob.Raw); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Collect memory ranges + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { + // + // Need memory above 1MB to be collected here + // + if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000 && + Hob.ResourceDescriptor->PhysicalStart < (EFI_PHYSICAL_ADDRESS) 0x100000000) { + *LowMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength); + } else if (Hob.ResourceDescriptor->PhysicalStart >= (EFI_PHYSICAL_ADDRESS) 0x100000000) { + *HighMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength); + } + } + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + + return EFI_SUCCESS; +} + +#endif +/** + 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; + UINT32 Pages; + VOID* Memory; + UINTN Size; + + // + // Allocate LM memory and configure PDM if enabled by user. + // ConfigureLM(PeiServices); + // + Status = (*PeiServices)->GetBootMode ( + (const EFI_PEI_SERVICES **)PeiServices, + &BootMode + ); + + if (BootMode != BOOT_ON_S3_RESUME) { + Size = (PcdGet32 (PcdFlashFvRecovery2Base) - PcdGet32 (PcdFlashFvMainBase)) + FixedPcdGet32(PcdFlashFvRecovery2Size); + Pages= Size/0x1000; + + Memory = AllocatePages ( Pages ); + CopyMem(Memory , (VOID *) FixedPcdGet32(PcdFlashFvMainBase) , Size); + + // + // We don't verify just load + // + PeiServicesInstallFvInfoPpi ( + NULL, + (VOID *) ((UINTN) Memory + (PcdGet32 (PcdFlashFvRecovery2Base) - PcdGet32 (PcdFlashFvMainBase))), + PcdGet32 (PcdFlashFvRecovery2Size), + NULL, + NULL + ); + + PeiServicesInstallFvInfoPpi ( + NULL, + (VOID *) Memory, + PcdGet32 (PcdFlashFvMainSize), + NULL, + NULL + ); + + } + + if (BootMode == BOOT_ON_S3_RESUME) { + PeiServicesInstallFvInfoPpi ( + NULL, + (VOID *) (UINTN) (PcdGet32 (PcdFlashFvRecovery2Base)), + PcdGet32 (PcdFlashFvRecovery2Size), + NULL, + NULL + ); + } + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/PlatformPei/Platform.c b/Vlv2TbltDevicePkg/PlatformPei/Platform.c new file mode 100644 index 0000000000..1dab9ca851 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/Platform.c @@ -0,0 +1,1063 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + +**/ + +#include "CommonHeader.h" + +#include "Platform.h" +#include +#include "PlatformBaseAddresses.h" +#include "PchAccess.h" +#include +#include "Platform.h" +#include "PchCommonDefinitions.h" +#include +#include +#include + +// +// Start::Alpine Valley platform +// +enum { + SMBUS_READ_BYTE, + SMBUS_WRITE_BYTE, + SMBUS_READ_BLOCK, + SMBUS_WRITE_BLOCK +}; + +#define EC_BASE 0xE0000000 + +// +// DEVICE 0 (Memroy Controller Hub) +// +#define MC_BUS 0x00 +#define MC_DEV 0x00 +#define MC_FUN 0x00 +#define MC_DEV_FUN (MC_DEV << 3) +#define MC_BUS_DEV_FUN ((MC_BUS << 8) + MC_DEV_FUN) + +// +// SysCtl SMBus address and block size +// +#define AV_SC_SMBUS_ADDRESS 0x60 +#define AV_SC_BYTE_LEN 1 +#define AV_SC_BLOCK_LEN 4 +#define AV_SC_SMBUS_WRCMD 1 +#define AV_SC_SMBUS_RDCMD 0 + +// +// SysCtl registers offset +// +#define AV_SC_REG_PLATFORM_ID 24 // 0x18 +#define AV_SC_REG_BOARD_ID 28 // 0x1C +#define AV_SC_REG_FAB_ID 32 // 0x20 +#define AV_SC_REG_ECO_ID 68 // 0x44 +#define AV_SC_REG_DDR_DAUGHTER_CARD_ID 144 // 0x90 +#define AV_SC_REG_SODIMM_CONFIG 36 + +// +// ID values +// +#define AV_SC_PLATFORM_ID_TABLET 0 +#define AV_SC_PLATFORM_ID_NETBOOK 2 +#define AV_SC_PLATFORM_ID_INTERPOSER 3 // Configuration TBD +#define AV_SC_BOARD_ID_AV_SVP 1492 + +#define BUS_TRIES 3 // How many times to retry on Bus Errors + +#define GTT_SIZE_1MB 1 +#define GTT_SIZE_2MB 2 + +#define PciCfg16Read( PciExpressBase, Bus, Device, Function, Register ) \ + MmioRead16(PciExpressBase + \ + (UINTN)(Bus << 20) + \ + (UINTN)(Device << 15) + \ + (UINTN)(Function << 12) + \ + (UINTN)(Register)) +#define PciCfg16Write( PciExpressBase, Bus, Device, Function, Register, Data ) \ + MmioWrite16(PciExpressBase + \ + (UINTN)(Bus << 20) + \ + (UINTN)(Device << 15) + \ + (UINTN)(Function << 12) + \ + (UINTN)(Register), \ + (UINT16)Data) + + +// +//Memory Test Manufacturing mode +// +UINT32 DataPatternForMemoryTest[] = { + 0x55555555, 0xAAAAAAAA, 0x55555510, 0x555555EF, 0x55555510, 0x555555EF, 0x55555510, 0x555555EF, + 0x55555555, 0xAAAAAAAA, 0x55551055, 0x5555EF55, 0x55551055, 0x5555EF55, 0x55551055, 0x5555EF55, + 0x55555555, 0xAAAAAAAA, 0x55105555, 0x55EF5555, 0x55105555, 0x55EF5555, 0x55105555, 0x55EF5555, + 0x55555555, 0xAAAAAAAA, 0x10555555, 0xEF555555, 0x10555555, 0xEF555555, 0x10555555, 0xEF555555 +}; +#define DATA_PATTERN_ARRAY_SIZE (sizeof(DataPatternForMemoryTest) / sizeof(UINT32)) + +// +//Memory Test Manufacturing mode +// +// +// The global indicator, the FvFileLoader callback will modify it to TRUE after loading PEIM into memory +// +BOOLEAN ImageInMemory = FALSE; + +EFI_STATUS +EFIAPI +Stall ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_STALL_PPI *This, + IN UINTN Microseconds + ); + +EFI_STATUS +EFIAPI +MfgMemoryTest ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN PEI_MFG_MEMORY_TEST_PPI *This, + IN UINT32 BeginAddress, + IN UINT32 MemoryLength + ); + +static EFI_PEI_STALL_PPI mStallPpi = { + PEI_STALL_RESOLUTION, + Stall +}; + +static PEI_MFG_MEMORY_TEST_PPI mPeiMfgMemoryTestPpi = { + MfgMemoryTest +}; + +static EFI_PEI_PPI_DESCRIPTOR mInstallStallPpi[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiPeiStallPpiGuid, + &mStallPpi + }, + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiMfgMemoryTestPpiGuid, + &mPeiMfgMemoryTestPpi + } + }; + +EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList[1] = { + { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiMemoryDiscoveredPpiGuid, + MemoryDiscoveredPpiNotifyCallback + } +}; + +EFI_STATUS +EFIAPI +InstallMonoStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + + +EFI_STATUS +ReadPlatformIds ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ); + +// +// Start::Alpine Valley platform +// +EFI_STATUS +PeiSmbusExec ( + UINT16 SmbusBase, + UINT8 SlvAddr, + UINT8 Operation, + UINT8 Offset, + UINT8 *Length, + UINT8 *Buffer + ); + +/** + This routine attempts to acquire the SMBus + + @retval FAILURE as failed + @retval SUCCESS as passed + +**/ +EFI_STATUS +AcquireBus ( + UINT16 SmbusBase + ) +{ + UINT8 StsReg; + + StsReg = 0; + StsReg = (UINT8)IoRead8(SmbusBase + R_PCH_SMBUS_HSTS); + if (StsReg & B_PCH_SMBUS_IUS) { + return EFI_DEVICE_ERROR; + } else if (StsReg & B_PCH_SMBUS_HBSY) { + // + // Clear Status Register and exit + // + // Wait for HSTS.HBSY to be clear + // + do { StsReg = (UINT8) IoRead8(SmbusBase+R_PCH_SMBUS_HSTS); } while ((StsReg & B_PCH_SMBUS_HBSY) != 0); + + // + // Clear all status bits + // + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, 0xFE); + return EFI_SUCCESS; + } else { + // + // Clear out any odd status information (Will Not Clear In Use) + // + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, StsReg); + return EFI_SUCCESS; + } +} +// +// End::Alpine Valley platform +// + +/** + This function checks the memory range in PEI. + + @param PeiServices Pointer to PEI Services. + @param This Pei memory test PPI pointer. + @param BeginAddress Beginning of the memory address to be checked. + @param MemoryLength Bytes of memory range to be checked. + @param Operation Type of memory check operation to be performed. + @param ErrorAddress Return the address of the error memory address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR Memory test failed. It's not safe to use this range of memory. + +**/ +EFI_STATUS +EFIAPI +MfgMemoryTest ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN PEI_MFG_MEMORY_TEST_PPI *This, + IN UINT32 BeginAddress, + IN UINT32 MemoryLength + ) +{ + UINT32 i; + UINT32 memAddr; + UINT32 readData; + UINT32 xorData; + UINT32 TestFlag = 0; + memAddr = BeginAddress; + + // + //Output Message for MFG + // + DEBUG ((EFI_D_ERROR, "MFGMODE SET\n")); + + // + //Writting the pattern in defined location. + // + while (memAddr < (BeginAddress+MemoryLength)) { + for (i = 0; i < DATA_PATTERN_ARRAY_SIZE; i++) { + if (memAddr > (BeginAddress+MemoryLength -4)) { + memAddr = memAddr + 4; + break; + } + *((volatile UINT32*) memAddr) = DataPatternForMemoryTest[i]; + memAddr = memAddr + 4; + } + } + + // + //Verify the pattern. + // + memAddr = BeginAddress; + while (memAddr < (BeginAddress+MemoryLength)) { + for (i = 0; i < DATA_PATTERN_ARRAY_SIZE; i++) { + if (memAddr > (BeginAddress+MemoryLength -4)) { + memAddr = memAddr + 4; + break; + } + readData = *((volatile UINT32*) memAddr); + xorData = readData ^ DataPatternForMemoryTest[i]; + + // + // If xorData is nonzero, this particular memAddr has a failure. + // + if (xorData != 0x00000000) { + DEBUG ((EFI_D_ERROR, "Expected value....: %x\n", DataPatternForMemoryTest[i])); + DEBUG ((EFI_D_ERROR, "ReadData value....: %x\n", readData)); + DEBUG ((EFI_D_ERROR, "Pattern failure at....: %x\n", memAddr)); + TestFlag = 1; + } + memAddr = memAddr + 4; + } + } + if (TestFlag) { + return EFI_DEVICE_ERROR; + } + + // + //Output Message for MFG + // + DEBUG ((EFI_D_ERROR, "MFGMODE MEMORY TEST PASSED\n")); + return EFI_SUCCESS; +} + +BOOLEAN +IsRtcUipAlwaysSet ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + + EFI_PEI_STALL_PPI *StallPpi; + UINTN Count; + + (**PeiServices).LocatePpi (PeiServices, &gEfiPeiStallPpiGuid, 0, NULL, (void **)&StallPpi); + + for (Count = 0; Count < 500; Count++) { // Maximum waiting approximates to 1.5 seconds (= 3 msec * 500) + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA); + if ((IoRead8 (R_PCH_RTC_TARGET2) & B_PCH_RTC_REGISTERA_UIP) == 0) { + return FALSE; + } + + StallPpi->Stall (PeiServices, StallPpi, 3000); + } + + return TRUE; +} + +EFI_STATUS +RtcPowerFailureHandler ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + + UINT16 DataUint16; + UINT8 DataUint8; + BOOLEAN RtcUipIsAlwaysSet; + DataUint16 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1); + RtcUipIsAlwaysSet = IsRtcUipAlwaysSet (PeiServices); + if ((DataUint16 & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) || (RtcUipIsAlwaysSet)) { + // + // Execute the sequence below. This will ensure that the RTC state machine has been initialized. + // + // Step 1. + // BIOS clears this bit by writing a '0' to it. + // + if (DataUint16 & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) { + // + // Set to invalid date in order to reset the time to + // BIOS build time later in the boot (SBRUN.c file). + // + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_YEAR); + IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_MONTH); + IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_DAYOFMONTH); + IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_DAYOFWEEK); + IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF); + + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_SECONDSALARM); + IoWrite8 (R_PCH_RTC_TARGET2, 0x00); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_MINUTESALARM); + IoWrite8 (R_PCH_RTC_TARGET2, 0x00); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_HOURSALARM); + IoWrite8 (R_PCH_RTC_TARGET2, 0x00); + } + + // + // Step 2. + // Set RTC Register 0Ah[6:4] to '110' or '111'. + // + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA); + IoWrite8 (R_PCH_RTC_TARGET2, (V_PCH_RTC_REGISTERA_DV_DIV_RST1 | V_PCH_RTC_REGISTERA_RS_976P5US)); + + // + // Step 3. + // Set RTC Register 0Bh[7]. + // + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB); + DataUint8 = (IoRead8 (R_PCH_RTC_TARGET2) | B_PCH_RTC_REGISTERB_SET); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB); + IoWrite8 (R_PCH_RTC_TARGET2, DataUint8); + + // + // Step 4. + // Set RTC Register 0Ah[6:4] to '010'. + // + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA); + IoWrite8 (R_PCH_RTC_TARGET2, (V_PCH_RTC_REGISTERA_DV_NORM_OP | V_PCH_RTC_REGISTERA_RS_976P5US)); + + // + // Step 5. + // Clear RTC Register 0Bh[7]. + // + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB); + DataUint8 = (IoRead8 (R_PCH_RTC_TARGET2) & (UINT8)~B_PCH_RTC_REGISTERB_SET); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB); + IoWrite8 (R_PCH_RTC_TARGET2, DataUint8); + } + + return EFI_SUCCESS; +} + + +VOID +PchBaseInit ( + VOID + ) +{ + // + // Program ACPI Power Management I/O Space Base Address + // + MmioWrite16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_BASE + ), + (UINT16)((ACPI_BASE_ADDRESS & B_PCH_LPC_ACPI_BASE_BAR) | B_PCH_LPC_ACPI_BASE_EN) + ); + + // + // Program GPIO Base Address + // + MmioWrite16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_BASE + ), + (UINT16)((GPIO_BASE_ADDRESS & B_PCH_LPC_GPIO_BASE_BAR) | B_PCH_LPC_GPIO_BASE_EN) + ); + + // + // Set PMC Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_PMC_BASE + ), + (UINT32)((PMC_BASE_ADDRESS & B_PCH_LPC_PMC_BASE_BAR) | B_PCH_LPC_PMC_BASE_EN) + ); + + // + // Set IO Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_IO_BASE + ), + (UINT32)((IO_BASE_ADDRESS & B_PCH_LPC_IO_BASE_BAR) | B_PCH_LPC_IO_BASE_EN) + ); + + // + // Set ILB Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ILB_BASE + ), + (UINT32)((ILB_BASE_ADDRESS & B_PCH_LPC_ILB_BASE_BAR) | B_PCH_LPC_ILB_BASE_EN) + ); + + // + // Set PUnit Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_PUNIT_BASE + ), + (UINT32)((PUNIT_BASE_ADDRESS & B_PCH_LPC_PUNIT_BASE_BAR) | B_PCH_LPC_PUNIT_BASE_EN) + ); + + // + // Set SPI Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_SPI_BASE + ), + (UINT32)((SPI_BASE_ADDRESS & B_PCH_LPC_SPI_BASE_BAR) | B_PCH_LPC_SPI_BASE_EN) + ); + + // + // Set Root Complex Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_RCBA + ), + (UINT32)((RCBA_BASE_ADDRESS & B_PCH_LPC_RCBA_BAR) | B_PCH_LPC_RCBA_EN) + ); + + // + // Set MPHY Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_MPHY_BASE + ), + (UINT32)((MPHY_BASE_ADDRESS & B_PCH_LPC_MPHY_BASE_BAR) | B_PCH_LPC_MPHY_BASE_EN) + ); + MmioWrite16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SMBUS, + PCI_FUNCTION_NUMBER_PCH_SMBUS, + R_PCH_SMBUS_BASE + ), + (UINT16)(SMBUS_BASE_ADDRESS & B_PCH_SMBUS_BASE_BAR) + ); + + MmioOr8 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SMBUS, + PCI_FUNCTION_NUMBER_PCH_SMBUS, + R_PCH_SMBUS_PCICMD + ), + B_PCH_SMBUS_PCICMD_IOSE + ); + +} + +/** + 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 + ) +{ + UINTN SmbusRegBase; + EFI_PLATFORM_INFO_HOB PlatformInfo; + EFI_STATUS Status= EFI_SUCCESS; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable = NULL; + UINTN VariableSize; + SYSTEM_CONFIGURATION SystemConfiguration; + UINT32 GGC = 0; + + EFI_PEI_PPI_DESCRIPTOR *mVlvMmioPolicyPpiDesc; + VLV_MMIO_POLICY_PPI *mVlvMmioPolicyPpi; + + ZeroMem (&PlatformInfo, sizeof(PlatformInfo)); + + Status = InstallMonoStatusCode(FileHandle, PeiServices); + ASSERT_EFI_ERROR (Status); + + + // + // Initialize Stall PPIs + // + Status = (*PeiServices)->InstallPpi (PeiServices, &mInstallStallPpi[0]); + ASSERT_EFI_ERROR (Status); + + Status = (*PeiServices)->NotifyPpi (PeiServices, &mMemoryDiscoveredNotifyList[0]); + ASSERT_EFI_ERROR (Status); + SmbusRegBase = PchPciDeviceMmBase ( + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SMBUS, + PCI_FUNCTION_NUMBER_PCH_SMBUS + ); + // + // Since PEI has no PCI enumerator, set the BAR & I/O space enable ourselves + // + MmioAndThenOr32 (SmbusRegBase + R_PCH_SMBUS_BASE, B_PCH_SMBUS_BASE_BAR, SMBUS_BASE_ADDRESS); + + MmioOr8 (SmbusRegBase + R_PCH_SMBUS_PCICMD, B_PCH_SMBUS_PCICMD_IOSE); + + PchBaseInit(); + + // + //Todo: confirm if we need program 8254 + // + // Setting 8254 + // Program timer 1 as refresh timer + // + IoWrite8 (0x43, 0x54); + IoWrite8 (0x41, 0x12); + + // + // RTC power failure handling + // + RtcPowerFailureHandler (PeiServices); + + + PchMmPci32( 0, 0, 2, 0, 0x50) = 0x210; + + VariableSize = sizeof (SYSTEM_CONFIGURATION); + ZeroMem (&SystemConfiguration, VariableSize); + + // + // Obtain variable services + // + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&Variable + ); + ASSERT_EFI_ERROR(Status); + Status = Variable->GetVariable ( + Variable, + L"Setup", + &gEfiSetupVariableGuid, + NULL, + &VariableSize, + &SystemConfiguration + ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR (Status)) { + GGC = ((2 << 3) | 0x200); + PciCfg16Write(EC_BASE, 0, 2, 0, 0x50, GGC); + GGC = PciCfg16Read(EC_BASE, 0, 2, 0, 0x50); + DEBUG((EFI_D_INFO , "GGC: 0x%08x GMSsize:0x%08x\n", GGC, (GGC & (BIT7|BIT6|BIT5|BIT4|BIT3))>>3)); + } else { + if (SystemConfiguration.Igd == 1 && SystemConfiguration.PrimaryVideoAdaptor != 2) { + GGC = (SystemConfiguration.IgdDvmt50PreAlloc << 3) | + (SystemConfiguration.GTTSize == GTT_SIZE_1MB ? 0x100: 0x200); + PciCfg16Write(EC_BASE, 0, 2, 0, 0x50, GGC); + GGC = PciCfg16Read(EC_BASE, 0, 2, 0, 0x50); + DEBUG((EFI_D_INFO , "GGC: 0x%08x GMSsize:0x%08x\n", GGC, (GGC & (BIT7|BIT6|BIT5|BIT4|BIT3))>>3)); + } + } + + // + // Initialize PlatformInfo HOB + // + Status = ReadPlatformIds(PeiServices, &PlatformInfo); + ASSERT_EFI_ERROR (Status); + + // + // 0 -> Disable , 1 -> Enable + // + if(SystemConfiguration.CfioPnpSettings == 1) { + DEBUG((EFI_D_INFO, "CheckCfioPnpSettings: CFIO Pnp Settings Enabled\n")); + PlatformInfo.CfioEnabled = 1; + } else { + DEBUG((EFI_D_INFO, "CheckCfioPnpSettings: CFIO Pnp Settings Disabled\n")); + PlatformInfo.CfioEnabled = 0; + } + + // + // Build HOB for PlatformInfo + // + BuildGuidDataHob ( + &gEfiPlatformInfoGuid, + &PlatformInfo, + sizeof (EFI_PLATFORM_INFO_HOB) + ); + + + // + // Set the new boot mode for MRC + // +#ifdef NOCS_S3_SUPPORT + Status = UpdateBootMode (PeiServices); + ASSERT_EFI_ERROR (Status); +#endif + + DEBUG((EFI_D_INFO, "Setup MMIO size ... \n\n")); + + // + // Setup MMIO size + // + Status = (*PeiServices)->AllocatePool( + PeiServices, + sizeof (EFI_PEI_PPI_DESCRIPTOR), + (void **)&mVlvMmioPolicyPpiDesc + ); + ASSERT_EFI_ERROR (Status); + Status = (*PeiServices)->AllocatePool( + PeiServices, + sizeof (VLV_MMIO_POLICY_PPI), + (void **)&mVlvMmioPolicyPpi + ); + ASSERT_EFI_ERROR (Status); + (*PeiServices)->SetMem ( + (VOID *)mVlvMmioPolicyPpi, + sizeof (VLV_MMIO_POLICY_PPI), + 0 + ); + mVlvMmioPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + mVlvMmioPolicyPpiDesc->Guid = &gVlvMmioPolicyPpiGuid; + mVlvMmioPolicyPpiDesc->Ppi = mVlvMmioPolicyPpi; + switch (SystemConfiguration.MmioSize) { + case 0: // 768MB + mVlvMmioPolicyPpi->MmioSize = 0x300; + break; + case 1: // 1GB + mVlvMmioPolicyPpi->MmioSize = 0x400; + break; + case 2: // 1.25GB + mVlvMmioPolicyPpi->MmioSize = 0x500; + break; + case 3: // 1.5GB + mVlvMmioPolicyPpi->MmioSize = 0x600; + break; + case 4: // 2GB + mVlvMmioPolicyPpi->MmioSize = 0x800; + break; + default: + mVlvMmioPolicyPpi->MmioSize = 0x800; + break; + } + Status = (*PeiServices)->InstallPpi( + PeiServices, + mVlvMmioPolicyPpiDesc + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +EFI_STATUS +ReadPlatformIds ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ) +{ + { + EFI_STATUS Status = EFI_SUCCESS; + UINT8 FabId = 0; + UINTN DataSize; + EFI_PLATFORM_INFO_HOB TmpHob; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiVar; + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&PeiVar + ); + ASSERT_EFI_ERROR (Status); + + DataSize = sizeof (EFI_PLATFORM_INFO_HOB); + Status = PeiVar->GetVariable ( + PeiVar, + L"PlatformInfo", + &gEfiVlv2VariableGuid, + NULL, + &DataSize, + &TmpHob + ); + + if (Status == EFI_SUCCESS) { + PlatformInfoHob->BoardId = TmpHob.BoardId; + PlatformInfoHob->MemCfgID = TmpHob.MemCfgID; + PlatformInfoHob->BoardRev = TmpHob.BoardRev; + PlatformInfoHob->PlatformFlavor = TmpHob.PlatformFlavor; + return Status; + } + + + PlatformInfoHob->BoardId = BOARD_ID_MINNOW2; + DEBUG ((EFI_D_INFO, "I'm Minnow2!\n")); + + PlatformInfoHob->MemCfgID = 0; + PlatformInfoHob->BoardRev = FabId + 1; // FabId = 0 means FAB1 (BoardRev = 1), FabId = 1 means FAB2 (BoardRev = 2)... + PlatformInfoHob->PlatformFlavor = FlavorMobile; + } + + return EFI_SUCCESS; +} + +// +// Start::Alpine Valley platform +// +/** + This routine reads SysCtl registers + + @param SmbusBase SMBUS Base Address + @param SlvAddr Targeted Smbus Slave device address + @param Operation Which SMBus protocol will be used + @param Offset Offset of the register + @param Length Number of bytes + @param Buffer Buffer contains values read from registers + + @retval SUCCESS as passed + @retval Others as failed + +**/ +EFI_STATUS +PeiSmbusExec ( + UINT16 SmbusBase, + UINT8 SlvAddr, + UINT8 Operation, + UINT8 Offset, + UINT8 *Length, + UINT8 *Buffer + ) +{ + EFI_STATUS Status=EFI_SUCCESS; + UINT8 AuxcReg; + UINT8 SmbusOperation = 0; + UINT8 StsReg; + UINT8 SlvAddrReg; + UINT8 HostCmdReg; + UINT8 BlockCount = 0; + BOOLEAN BufferTooSmall; + UINT8 Index; + UINT8 *CallBuffer; + UINT8 RetryCount = BUS_TRIES; + + // + // MrcSmbusExec supports byte and block read. + // Only allow Byte or block access + // + if (!((*Length == AV_SC_BYTE_LEN) || (*Length == AV_SC_BLOCK_LEN))) { + return EFI_INVALID_PARAMETER; + } + + // + // See if its ok to use the bus based upon INUSE_STS bit. + // + Status = AcquireBus (SmbusBase); + ASSERT_EFI_ERROR(Status); + + CallBuffer = Buffer; + + // + //SmbStatus Bits of interest + //[6] = IUS (In Use Status) + //[4] = FAIL + //[3] = BERR (Bus Error = transaction collision) + //[2] = DERR (Device Error = Illegal Command Field, Unclaimed Cycle, Host Device Timeout, CRC Error) + //[1] = INTR (Successful completion of last command) + //[0] = HOST BUSY + // + // + // This is the main operation loop. If the operation results in a Smbus + // collision with another master on the bus, it attempts the requested + // transaction again at least BUS_TRIES attempts. + // + while (RetryCount--) { + // + // Operation Specifics (pre-execution) + // + Status = EFI_SUCCESS; + SlvAddrReg = SlvAddr; + HostCmdReg = Offset; + AuxcReg = 0; + + switch (Operation) { + + case SMBUS_WRITE_BYTE: + IoWrite8 (SmbusBase+R_PCH_SMBUS_HD0, CallBuffer[0]); + SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE_DATA; + break; + + case SMBUS_READ_BYTE: + SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE_DATA; + SlvAddrReg |= B_PCH_SMBUS_RW_SEL_READ; + if (*Length < 1) { + Status = EFI_INVALID_PARAMETER; + } + *Length = 1; + break; + + case SMBUS_WRITE_BLOCK: + SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK; + IoWrite8 (SmbusBase+R_PCH_SMBUS_HD0, *(UINT8 *) Length); + BlockCount = (UINT8) (*Length); + if ((*Length < 1) || (*Length > 32)) { + Status = EFI_INVALID_PARAMETER; + break; + } + AuxcReg |= B_PCH_SMBUS_E32B; + break; + + case SMBUS_READ_BLOCK: + SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK; + SlvAddrReg |= B_PCH_SMBUS_RW_SEL_READ; + if ((*Length < 1) || (*Length > 32)) { + Status = EFI_INVALID_PARAMETER; + break; + } + AuxcReg |= B_PCH_SMBUS_E32B; + break; + + default: + Status = EFI_INVALID_PARAMETER; + break; + } + + // + // Set Auxiliary Control register + // + IoWrite8 (SmbusBase+R_PCH_SMBUS_AUXC, AuxcReg); + + // + // Reset the pointer of the internal buffer + // + IoRead8 (SmbusBase+R_PCH_SMBUS_HCTL); + + // + // Now that the 32 byte buffer is turned on, we can write th block data + // into it + // + if (Operation == SMBUS_WRITE_BLOCK) { + for (Index = 0; Index < BlockCount; Index++) { + // + // Write next byte + // + IoWrite8 (SmbusBase+R_PCH_SMBUS_HBD, CallBuffer[Index]); + } + } + + // + // Set SMBus slave address for the device to read + // + IoWrite8(SmbusBase+R_PCH_SMBUS_TSA, SlvAddrReg); + + // + // + // Set Command register for the offset to read + // + IoWrite8(SmbusBase+R_PCH_SMBUS_HCMD, HostCmdReg ); + + // + // Set Control Register to Set "operation command" protocol and start bit + // + IoWrite8(SmbusBase+R_PCH_SMBUS_HCTL, (UINT8) (SmbusOperation + B_PCH_SMBUS_START)); + + // + // Wait for IO to complete + // + do { StsReg = (UINT8) IoRead8(SmbusBase+0); } while ((StsReg & (BIT4|BIT3|BIT2|BIT1)) == 0); + + if (StsReg & B_PCH_SMBUS_DERR) { + Status = EFI_DEVICE_ERROR; + break; + } else if (StsReg & B_PCH_SMBUS_BERR) { + // + // Clear the Bus Error for another try + // + Status = EFI_DEVICE_ERROR; + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR); + + // + // Clear Status Registers + // + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL); + IoWrite8(SmbusBase+R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE); + + continue; + } + + // + // successfull completion + // Operation Specifics (post-execution) + // + switch (Operation) { + + case SMBUS_READ_BYTE: + CallBuffer[0] = (UINT8)(IoRead8 (SmbusBase+R_PCH_SMBUS_HD0)); + break; + + case SMBUS_WRITE_BLOCK: + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BYTE_DONE_STS); + break; + + case SMBUS_READ_BLOCK: + BufferTooSmall = FALSE; + + // + // Find out how many bytes will be in the block + // + BlockCount = (UINT8)(IoRead8 (SmbusBase+R_PCH_SMBUS_HD0)); + if (*Length < BlockCount) { + BufferTooSmall = TRUE; + } else { + for (Index = 0; Index < BlockCount; Index++) { + // + // Read the byte + // + CallBuffer[Index] = (UINT8)IoRead8 (SmbusBase+R_PCH_SMBUS_HBD); + } + } + + *Length = BlockCount; + if (BufferTooSmall) { + Status = EFI_BUFFER_TOO_SMALL; + } + break; + + default: + break; + }; + + if ((StsReg & B_PCH_SMBUS_BERR) && (Status == EFI_SUCCESS)) { + // + // Clear the Bus Error for another try + // + Status = EFI_DEVICE_ERROR; + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR); + + continue; + } else { + break; + } + } + + // + // Clear Status Registers and exit + // + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL); + IoWrite8(SmbusBase+R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE); + IoWrite8(SmbusBase+R_PCH_SMBUS_AUXC, 0); + return Status; +} +// +// End::Alpine Valley platform +// + diff --git a/Vlv2TbltDevicePkg/PlatformPei/Platform.h b/Vlv2TbltDevicePkg/PlatformPei/Platform.h new file mode 100644 index 0000000000..12e4b658d0 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/Platform.h @@ -0,0 +1,216 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +**/ + + +#ifndef __PEI_PLATFORM_H__ +#define __PEI_PLATFORM_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) + +#ifdef NOCS_S3_SUPPORT + +/** + 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 CONST EFI_PEI_SERVICES **PeiServices + ); +#endif + +/** + 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 + ); + +/** + 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 +InitializeRecovery ( + IN EFI_PEI_SERVICES **PeiServices + ); + +/** + This function + 1. Calling MRC to initialize memory. + 2. Install EFI Memory. + 3. Capsule coalesce if capsule boot mode. + 4. 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 + ); + +/** + 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 + ); + +/** + This function provides the implementation to properly setup both LM & PDM functionality. + + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS Procedure returned successfully. + +**/ +EFI_STATUS +ConfigureLM( + IN EFI_PEI_SERVICES **PeiServices + ); + +#include + +BOOLEAN +EFIAPI +IsFastBootEnabled ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +PrioritizeBootMode ( + IN OUT EFI_BOOT_MODE *CurrentBootMode, + IN EFI_BOOT_MODE NewBootMode + ); + +EFI_STATUS +EFIAPI +CapsulePpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); +#endif diff --git a/Vlv2TbltDevicePkg/PlatformPei/PlatformPei.inf b/Vlv2TbltDevicePkg/PlatformPei/PlatformPei.inf new file mode 100644 index 0000000000..af8bb19083 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/PlatformPei.inf @@ -0,0 +1,136 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# 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. Capsule coalesce if capsule boot mode. +# 3. Create HOB of system memory. +# Note: MRC supports 3 kinds of chipsets including Lakeport, Glenwood and Mukilteo, +# so please don't define MACRO MUKILTEO_SUPPORT on Lakeport here. +# +# On post memory, following action is performed, +# 1. TC 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 +# IntelTCLib, TCAccess 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. +# +# + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformPeim + FILE_GUID = 9618C0DC-50A4-496c-994F-7241F282ED01 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = PeiInitPlatform + PI_SPECIFICATION_VERSION = 0x0001000A + +[sources.common] + Platform.c + Platform.h + MemoryCallback.c + CommonHeader.h + Stall.c + BootMode.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + IA32FamilyCpuPkg/IA32FamilyCpuPkg.dec + UefiCpuPkg/UefiCpuPkg.dec + CryptoPkg/CryptoPkg.dec + EdkCompatibilityPkg/EdkCompatibilityPkg.dec + +[LibraryClasses] + PeimEntryPoint + DebugLib + HobLib + IoLib + MultiPlatformLib + MtrrLib + PerformanceLib + MonoStatusCodeLib + BaseCryptLib + PciLib + +[Ppis] + gEfiPeiStallPpiGuid + gPeiSpeakerInterfacePpiGuid + gEfiPeiMemoryDiscoveredPpiGuid + gVlvPolicyPpiGuid + gEfiPeiReadOnlyVariable2PpiGuid + gEfiPeiResetPpiGuid + gEfiEndOfPeiSignalPpiGuid + gEfiFindFvPpiGuid + gPeiCapsulePpiGuid + gEfiPeiBootInRecoveryModePpiGuid + gEfiPeiRecoveryModulePpiGuid + gEfiPeiDeviceRecoveryModulePpiGuid + gPeiCachePpiGuid + gEfiPeiMasterBootModePpiGuid + gEfiPeiSmbusPpiGuid + gPeiMfgMemoryTestPpiGuid + gPeiSha256HashPpiGuid + gVlvMmioPolicyPpiGuid + +[Guids] + gEfiSetupVariableGuid + gEfiPlatformInfoGuid + gEfiPlatformBootModeGuid + gEfiPlatformCpuInfoGuid + gEfiGlobalVariableGuid + gRecoveryOnFatFloppyDiskGuid + gRecoveryOnFatUsbDiskGuid + gRecoveryOnFatIdeDiskGuid + gRecoveryOnDataCdGuid + gMfgModeVariableGuid + gEfiNormalSetupGuid + gEfiBootStateGuid + gEfiVlv2VariableGuid + +[Pcd.common] + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainBase + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainSize + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Base + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Size + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress + gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize +[Depex] + TRUE + diff --git a/Vlv2TbltDevicePkg/PlatformPei/Stall.c b/Vlv2TbltDevicePkg/PlatformPei/Stall.c new file mode 100644 index 0000000000..8c2ab99f1c --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/Stall.c @@ -0,0 +1,95 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Stall.c + +Abstract: + + Produce Stall Ppi. + +--*/ + + +#include "CommonHeader.h" +#include "PlatformBaseAddresses.h" +#include "PchRegs.h" + +/** + Waits for at least the given number of microseconds. + + @param PeiServices General purpose services available to every PEIM. + @param This PPI instance structure. + @param Microseconds Desired length of time to wait. + + @retval EFI_SUCCESS If the desired amount of time was passed. + +**/ +EFI_STATUS +EFIAPI +Stall ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_STALL_PPI *This, + IN UINTN Microseconds + ) +{ + UINTN Ticks; + UINTN Counts; + UINT32 CurrentTick; + UINT32 OriginalTick; + UINT32 RemainingTick; + + if (Microseconds == 0) { + return EFI_SUCCESS; + } + + OriginalTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR); + OriginalTick &= (V_PCH_ACPI_PM1_TMR_MAX_VAL - 1); + CurrentTick = OriginalTick; + + // + // The timer frequency is 3.579545MHz, so 1 ms corresponds to 3.58 clocks + // + Ticks = Microseconds * 358 / 100 + OriginalTick + 1; + + // + // The loops needed for timer overflow + // + Counts = (UINTN)RShiftU64((UINT64)Ticks, 24); + + // + // Remaining clocks within one loop + // + RemainingTick = Ticks & 0xFFFFFF; + + // + // Do not intend to use TMROF_STS bit of register PM1_STS, because this add extra + // one I/O operation, and may generate SMI + // + while (Counts != 0) { + CurrentTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR) & B_PCH_ACPI_PM1_TMR_VAL; + if (CurrentTick <= OriginalTick) { + Counts--; + } + OriginalTick = CurrentTick; + } + + while ((RemainingTick > CurrentTick) && (OriginalTick <= CurrentTick)) { + OriginalTick = CurrentTick; + CurrentTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR) & B_PCH_ACPI_PM1_TMR_VAL; + } + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/PlatformPkg.dec b/Vlv2TbltDevicePkg/PlatformPkg.dec new file mode 100644 index 0000000000..378cb530d2 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPkg.dec @@ -0,0 +1,208 @@ +#/** @file +# Platform Package +# +# This package provides platform specific modules. +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +#**/ + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = PlatformPkg + PACKAGE_GUID = 463B3B00-0D18-4a5f-90C0-D5B851D2574B + PACKAGE_VERSION = 0.1 + +[Includes] + . + Include + Include/Library + +[Ppis] + gPeiSpeakerInterfacePpiGuid = { 0x30ac275e, 0xbb30, 0x4b84, { 0xa1, 0xcd, 0x0a, 0xf1, 0x32, 0x2c, 0x89, 0xc0 }} + gPeiUsbControllerPpiGuid = { 0x3BC1F6DE, 0x693E, 0x4547, { 0xA3, 0x00, 0x21, 0x82, 0x3C, 0xA4, 0x20, 0xB2 }} + gPeiMfgMemoryTestPpiGuid = { 0xab294a92, 0xeaf5, 0x4cf3, { 0xab, 0x2b, 0x2d, 0x4b, 0xed, 0x4d, 0xb6, 0x3d }} + gPeiSha256HashPpiGuid = { 0x950e191b, 0x8524, 0x4f51, { 0x80, 0xa1, 0x5c, 0x4f, 0x1b, 0x03, 0xf3, 0x5c }} + +[Guids] + gEfiPlatformBootModeGuid = { 0xce845704, 0x1683, 0x4d38, { 0xa4, 0xf9, 0x7d, 0x0b, 0x50, 0x77, 0x57, 0x93 } } + gEfiPlatformInfoGuid = { 0x1e2acc41, 0xe26a, 0x483d, { 0xaf, 0xc7, 0xa0, 0x56, 0xc3, 0x4e, 0x08, 0x7b } } + gEfiMemoryConfigDataGuid = { 0x80dbd530, 0xb74c, 0x4f11, { 0x8c, 0x03, 0x41, 0x86, 0x65, 0x53, 0x28, 0x31 } } + gPlatformModuleTokenSpaceGuid = { 0x69d13bf0, 0xaf91, 0x4d96, { 0xaa, 0x9f, 0x21, 0x84, 0xc5, 0xce, 0x3b, 0xc0 } } + gEfiSerialPortTokenSpaceGuid = { 0x5fad2389, 0x2bc7, 0x4bd2, { 0x83, 0xd3, 0x42, 0x9f, 0xb6, 0xae, 0xa3, 0x3f } } + gEfiIchTokenSpaceGuid = { 0xe38c11e3, 0x968f, 0x47b8, { 0xac, 0xef, 0xac, 0xc0, 0x69, 0x3d, 0xb9, 0xff } } + gEfiPchTokenSpaceGuid = { 0x89a1b278, 0xa1a1, 0x4df7, { 0xb1, 0x37, 0xde, 0x5a, 0xd7, 0xc4, 0x79, 0x13 } } + gEfiSioVariableGuid = { 0x560bf58a, 0x1e0d, 0x4d7e, { 0x95, 0x3f, 0x29, 0x80, 0xa2, 0x61, 0xe0, 0x31 } } + gProcessorProducerGuid = { 0x1bf06aea, 0x5bec, 0x4a8d, { 0x95, 0x76, 0x74, 0x9b, 0x09, 0x56, 0x2d, 0x30 } } + gEfiPowerOnHobGuid = { 0x0468a601, 0xc535, 0x46fd, { 0xa9, 0x5d, 0xbb, 0xab, 0x99, 0x1b, 0x17, 0x8c } } + gEfiPlatformCpuInfoGuid = { 0xbb9c7ab7, 0xb8d9, 0x4bf3, { 0x9c, 0x29, 0x9b, 0xf3, 0x41, 0xe2, 0x17, 0xbc } } + gEfiBiosIdGuid = { 0xC3E36D09, 0x8294, 0x4b97, { 0xA8, 0x57, 0xD5, 0x28, 0x8F, 0xE3, 0x3E, 0x28 } } + gEfiPlatformBootModeGuid = { 0xce845704, 0x1683, 0x4d38, { 0xa4, 0xf9, 0x7d, 0x0b, 0x50, 0x77, 0x57, 0x93 } } + gEfiBoardFeaturesGuid = { 0x94b9e8ae, 0x8877, 0x479a, { 0x98, 0x42, 0xf5, 0x97, 0x4b, 0x82, 0xce, 0xd3 } } + gItkDataVarGuid = { 0x3812723d, 0x7e48, 0x4e29, { 0xbc, 0x27, 0xf5, 0xa3, 0x9a, 0xc9, 0x4e, 0xf1 } } + gDmiDataGuid = { 0x70e56c5e, 0x280c, 0x44b0, { 0xa4, 0x97, 0x09, 0x68, 0x1a, 0xbc, 0x37, 0x5e } } + gIdccDataHubGuid = { 0x788e1d9f, 0x1eab, 0x47d2, { 0xa2, 0xf3, 0x78, 0xca, 0xe8, 0x7d, 0x60, 0x12 } } + gEfiSetupVariableGuid = { 0xec87d643, 0xeba4, 0x4bb5, { 0xa1, 0xe5, 0x3f, 0x3e, 0x36, 0xb2, 0x0d, 0xa9 } } + gEfiPlatformInfoGuid = { 0x1e2acc41, 0xe26a, 0x483d, { 0xaf, 0xc7, 0xa0, 0x56, 0xc3, 0x4e, 0x08, 0x7b } } + gMfgModeVariableGuid = { 0xEF14FD78, 0x0793, 0x4e2b, { 0xAC, 0x6D, 0x06, 0x28, 0x47, 0xE0, 0x17, 0x91 } } + gEfiAcpiTableStorageGuid = { 0x7e374e25, 0x8e01, 0x4fee, { 0x87, 0xf2, 0x39, 0x0c, 0x23, 0xc6, 0x06, 0xcd } } + gACPIOSFRMfgStringVariableGuid = { 0x72234213, 0x0fd7, 0x48a1, { 0xa5, 0x9f, 0xb4, 0x1b, 0xc1, 0x07, 0xfb, 0xcd } } + gACPIOSFRRefDataBlockVariableGuid = { 0x72234213, 0x0fd7, 0x48a1, { 0xa5, 0x9f, 0xb4, 0x1b, 0xc1, 0x07, 0xfb, 0xcd } } + gACPIOSFRModelStringVariableGuid = { 0xca1bcad9, 0xe021, 0x4547, { 0xa1, 0xb0, 0x5b, 0x22, 0xc7, 0xf6, 0x87, 0xf4 } } + gEfiAcpiTableStorageGuid = { 0x7e374e25, 0x8e01, 0x4fee, { 0x87, 0xf2, 0x39, 0x0c, 0x23, 0xc6, 0x06, 0xcd } } + gEfiPciLanInfoGuid = { 0x0d9a1427, 0xe02a, 0x437d, { 0x92, 0x6b, 0xaa, 0x52, 0x1f, 0xd7, 0x22, 0xba } } + gEfiNormalSetupGuid = { 0xec87d643, 0xeba4, 0x4bb5, { 0xa1, 0xe5, 0x3f, 0x3e, 0x36, 0xb2, 0x0d, 0xa9 } } + gFirmwareIdGuid = { 0x5e559c23, 0x1faa, 0x4ae1, { 0x8d, 0x4a, 0xc6, 0xcf, 0x02, 0x6c, 0x76, 0x6f } } + gBmpImageGuid = { 0x878AC2CC, 0x5343, 0x46F2, { 0xB5, 0x63, 0x51, 0xF8, 0x9D, 0xAF, 0x56, 0xBA } } + gOsSelectionVariableGuid = { 0x86843f56, 0x675d, 0x40a5, { 0x95, 0x30, 0xbc, 0x85, 0x83, 0x72, 0xf1, 0x03 } } + +[Protocols] + gEfiActiveBiosProtocolGuid = { 0xebbe2d1b, 0x1647, 0x4bda, { 0xab, 0x9a, 0x78, 0x63, 0xe3, 0x96, 0xd4, 0x1a } } + gEfiPlatformCpuProtocolGuid = { 0xbd26cdc9, 0xa092, 0x462a, { 0x87, 0x7a, 0x5a, 0xb6, 0xad, 0xce, 0x48, 0x12 } } + gDxePchPlatformPolicyProtocolGuid = { 0x4b0165a9, 0x61d6, 0x4e23, { 0xa0, 0xb5, 0x3e, 0xc7, 0x9c, 0x2e, 0x30, 0xd5 } } + gEfiTpmMpDriverProtocolGuid = { 0xde161cfe, 0x1e60, 0x42a1, { 0x8c, 0xc3, 0xee, 0x7e, 0xf0, 0x73, 0x52, 0x12 } } + gEfiLpcWpce791PolicyProtocolGuid = { 0xab2bee2f, 0xc1a6, 0x4399, { 0x85, 0x3d, 0xc0, 0x7c, 0x77, 0x4f, 0xfd, 0x0d } } + gUsbPolicyGuid = { 0xf617b358, 0x12cf, 0x414a, { 0xa0, 0x69, 0x60, 0x67, 0x7b, 0xda, 0x13, 0xb4 } } + gEfiSpeakerInterfaceProtocolGuid = { 0x400b4476, 0x3081, 0x11d6, { 0x87, 0xed, 0x00, 0x06, 0x29, 0x45, 0xc3, 0xb9 } } + gDxeVlvPlatformPolicyGuid = { 0x5bab88ba, 0xe0e2, 0x4674, { 0xb6, 0xad, 0xb8, 0x12, 0xf6, 0x88, 0x1c, 0xd6 } } + gEfiSmbiosSlotPopulationGuid = { 0xef7bf7d6, 0xf8ff, 0x4a76, { 0x82, 0x47, 0xc0, 0xd0, 0xd1, 0xcc, 0x49, 0xc0 } } + gObservableProtocolGuid = { 0xe227c522, 0xd5fe, 0x4a53, { 0x87, 0xb1, 0x0f, 0xbe, 0x57, 0x0f, 0x98, 0xe9 } } + gEfiCk505ClockPlatformInfoGuid = { 0x3c485ea4, 0x449a, 0x46ce, { 0xbb, 0x08, 0x2a, 0x33, 0x6e, 0xa9, 0x6b, 0x4e } } + gEfiLpcWpc83627PolicyProtocolGuid = { 0xd3ecc567, 0x9fd5, 0x44c1, { 0x86, 0xcf, 0x5d, 0xa7, 0xa2, 0x4f, 0x4b, 0x5d } } + gEfiTcoResetProtocolGuid = { 0xa6a79162, 0xe325, 0x4c30, { 0xbc, 0xc3, 0x59, 0x37, 0x30, 0x64, 0xef, 0xb3 } } + gEfiWatchdogTimerDriverProtocolGuid = { 0xd5b06d16, 0x2ea1, 0x4def, { 0x98, 0xd0, 0xa0, 0x5d, 0x40, 0x72, 0x84, 0x17 } } + gEfiPlatformIdeInitProtocolGuid = { 0x377c66a3, 0x8fe7, 0x4ee8, { 0x85, 0xb8, 0xf1, 0xa2, 0x82, 0x56, 0x9e, 0x3b } } + gEfiPciPlatformProtocolGuid = { 0x07d75280, 0x27d4, 0x4d69, { 0x90, 0xd0, 0x56, 0x43, 0xe2, 0x38, 0xb3, 0x41 } } + gEnhancedSpeedstepProtocolGuid = { 0x91a1ddcf, 0x5374, 0x4939, { 0x89, 0x51, 0xd7, 0x29, 0x3f, 0x1a, 0x78, 0x6f } } + gEfiAcpiSupportProtocolGuid = { 0xdbff9d55, 0x89b7, 0x46da, { 0xbd, 0xdf, 0x67, 0x7d, 0x3d, 0xc0, 0x24, 0x1d } } + gEfiAcpiS3SaveProtocolGuid = { 0x125f2de1, 0xfb85, 0x440c, { 0xa5, 0x4c, 0x4d, 0x99, 0x35, 0x8a, 0x8d, 0x38 } } + gEfiCpuIoProtocolGuid = { 0xB0732526, 0x38C8, 0x4b40, { 0x88, 0x77, 0x61, 0xC7, 0xB0, 0x6A, 0xAC, 0x45 } } + gPlatformGOPPolicyGuid = { 0xec2e931b, 0x3281, 0x48a5, { 0x81, 0x07, 0xdf, 0x8a, 0x8b, 0xed, 0x3c, 0x5d } } + gEfiGopDisplayBrightnessProtocolGuid = { 0x6ff23f1d, 0x877c, 0x4b1b, { 0x93, 0xfc, 0xf1, 0x42, 0xb2, 0xee, 0xa6, 0xa7 } } + gEfiUsbKeyboardConnectGuid = { 0xad9c4381, 0x1ede, 0x430c, { 0x8d, 0x42, 0x23, 0x76, 0x7c, 0x46, 0x5d, 0x52 } } + + +[PcdsFixedAtBuild] + gPlatformModuleTokenSpaceGuid.PcdFlashNvStorageBase|0xFFF60000|UINT32|0x20000007 + gPlatformModuleTokenSpaceGuid.PcdFlashNvStorageSize|0x00010000|UINT32|0x20000008 + gPlatformModuleTokenSpaceGuid.PcdFlashNvStorageEventLogBase|0xFFF6C000|UINT32|0x30000007 + gPlatformModuleTokenSpaceGuid.PcdFlashNvStorageEventLogSize|0x00002000|UINT32|0x30000008 + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoveryBase|0xFFF80000|UINT32|0x20000004 + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoverySize|0x00080000|UINT32|0x20000005 + gPlatformModuleTokenSpaceGuid.PcdFlashFvShellBase|0xFFF50000|UINT32|0x20000009 + gPlatformModuleTokenSpaceGuid.PcdFlashFvShellSize|0x00000000|UINT32|0x20000010 + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainBase|0xFF800000|UINT32|0x20000001 + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainSize|0x00500000|UINT32|0x20000002 + gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress|0xFF800000|UINT32|0x10000001 + gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize|0x00800000|UINT32|0x10000002 + gPlatformModuleTokenSpaceGuid.PcdFlashTestMenuBase|0xFF000000|UINT32|0x20000011 + gPlatformModuleTokenSpaceGuid.PcdFlashTestMenuSize|0x00010000|UINT32|0x20000012 + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Base|0xFFFA0000|UINT32|0x20000013 + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Size|0x00040000|UINT32|0x20000014 + gPlatformModuleTokenSpaceGuid.PcdFlashMicroCodeAddress|0xFFF90000|UINT32|0x20000015 + gPlatformModuleTokenSpaceGuid.PcdFlashMicroCodeSize|0x00002000|UINT32|0x20000016 + gPlatformModuleTokenSpaceGuid.PcdFlashMicroCode2Address|0xFFF92000|UINT32|0x20000017 + gPlatformModuleTokenSpaceGuid.PcdFlashMicroCode2Size|0x0000C800|UINT32|0x20000018 + gPlatformModuleTokenSpaceGuid.PcdIFWISigBaseAddress|0x0F00|UINT32|0x20000019 + gPlatformModuleTokenSpaceGuid.PcdPBTNDisableInterval|0x01F4|UINT32|0x2000001A + gPlatformModuleTokenSpaceGuid.PcdTouchAttributes|2|UINT32|0x20000020 + gPlatformModuleTokenSpaceGuid.PcdTouchCIDString|"I2C05\\S004A"|VOID*|0x20000021 + gPlatformModuleTokenSpaceGuid.PcdFullIconFile |{ 0x69, 0x00, 0x39, 0x82, 0x30, 0xa6, 0x4b, 0x4c, 0x85, 0xfc, 0x95, 0xe9, 0x49, 0xc9, 0xf0, 0x76 }|VOID*|0x20000022 + gPlatformModuleTokenSpaceGuid.PcdSimpleIconFile |{ 0x4b, 0xf7, 0xee, 0x4b, 0x30, 0xa3, 0x49, 0x67, 0xa4, 0xad, 0xa4, 0xb1, 0xca, 0xe4, 0x4b, 0x0d }|VOID*|0x20000023 + gPlatformModuleTokenSpaceGuid.PcdCapitalLetterKeyboardFile|{ 0x82, 0x38, 0x75, 0xd8, 0x83, 0xa2, 0x4c, 0x37, 0xb6, 0xea, 0x04, 0xac, 0xc3, 0x06, 0x0f, 0x07 }|VOID*|0x20000024 + gPlatformModuleTokenSpaceGuid.PcdSmallLetterKeyboardFile |{ 0x4c, 0x66, 0x39, 0xa2, 0x09, 0x0e, 0x4d, 0xc9, 0x9f, 0x55, 0x0f, 0xcb, 0x72, 0x60, 0x26, 0x11 }|VOID*|0x20000025 + gPlatformModuleTokenSpaceGuid.PcdDigitKeyboardFile |{ 0x3f, 0xfe, 0x2c, 0x17, 0x92, 0x5d, 0x49, 0x7d, 0x87, 0x0a, 0x46, 0x14, 0xe4, 0x58, 0xd8, 0x5e }|VOID*|0x20000026 + gPlatformModuleTokenSpaceGuid.PcdSimpleKeyboardFile |{ 0x5c, 0xd4, 0xfc, 0x98, 0xbf, 0x79, 0x41, 0x10, 0xa2, 0xd3, 0x87, 0xbe, 0x82, 0xd0, 0x90, 0x52 }|VOID*|0x20000027 + + gPlatformModuleTokenSpaceGuid.PcdFlashSpidOffset|0x1000|UINT32|0x2000002A + gPlatformModuleTokenSpaceGuid.PcdFlashSpidSize|0x00001000|UINT32|0x2000002B + gPlatformModuleTokenSpaceGuid.PcdFlashEmOffset|0x3000|UINT32|0x2000002C + gPlatformModuleTokenSpaceGuid.PcdFlashEmSize|0x1000|UINT32|0x2000002D + + gEfiSerialPortTokenSpaceGuid.PcdSerialRegisterBase|0x3f8|UINT64|0x00000001 + gEfiSerialPortTokenSpaceGuid.PcdSerialBoudRate|115200|UINT32|0x00000002 + + gEfiPchTokenSpaceGuid.PcdPchAcpiIoPortBaseAddress|0x400|UINT16|0x0000000B + + ## FFS filename to find the shell application. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0xB7, 0xD6, 0x7A, 0xC5, 0x15, 0x05, 0xA8, 0x40, 0x9D, 0x21, 0x55, 0x16, 0x52, 0x85, 0x4E, 0x37 }|VOID*|0x40000004 + + gEfiIchTokenSpaceGuid.PcdPeiIchUhciControllerIoPortBaseAddress|0x4000|UINT16|0x30000017 + gEfiIchTokenSpaceGuid.PcdPeiIchEhciControllerMemoryBaseAddress|0xFD000000|UINT32|0x30000019 + + + gPlatformModuleTokenSpaceGuid.PcdRamLogBaseAddress|0x20000|UINT32|0x00000013 + gPlatformModuleTokenSpaceGuid.PcdRamLogBaseLength|0x80000|UINT32|0x00000014 + gPlatformModuleTokenSpaceGuid.PcdRamLogBaseCarAddress|0xFEF86000|UINT32|0x00000015 + gPlatformModuleTokenSpaceGuid.PcdRamLogBaseCarLength|0x2000|UINT32|0x00000016 + + + #Pcd for Flash Update tool + gPlatformModuleTokenSpaceGuid.PcdFlashChipBase|0xFF800000|UINT32|0x40000001 + gPlatformModuleTokenSpaceGuid.PcdFlashChipSize|0x00800000|UINT32|0x40000002 + gPlatformModuleTokenSpaceGuid.PcdFlashDescriptorBase|0xFF800000|UINT32|0x40000003 + gPlatformModuleTokenSpaceGuid.PcdFlashDescriptorSize|0x00001000|UINT32|0x40000004 + gPlatformModuleTokenSpaceGuid.PcdTxeRomBase|0xFF801000|UINT32|0x40000009 + gPlatformModuleTokenSpaceGuid.PcdTxeRomSize|0x004FF000|UINT32|0x4000000A + gPlatformModuleTokenSpaceGuid.PcdBiosRomBase|0xFFD00000|UINT32|0x4000000B + gPlatformModuleTokenSpaceGuid.PcdBiosRomSize|0x00300000|UINT32|0x4000000C + +[PcdsFeatureFlag] + ## This PCD specifies whether StatusCode is reported via ISA Serial port. + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseIsaSerial|TRUE|BOOLEAN|0x00000020 + + ## This PCD specifies whether StatusCode is reported via USB Serial port. + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseUsbSerial|TRUE|BOOLEAN|0x00000021 + + ## This PCD specifies whether StatusCode is reported via RAM. + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseRam|FALSE|BOOLEAN|0x00000022 + + ## Platform BDS PCD to control whether to dispatch additional option rom, e.g.: PXE, AHCI + gPlatformModuleTokenSpaceGuid.PcdBdsDispatchAdditionalOprom|TRUE|BOOLEAN|0x00000024 + + #new added feature for BIOS usb recovery + gEfiIchTokenSpaceGuid.PcdEhciRecoveryEnabled|TRUE|BOOLEAN|0x00000026 + +[PcdsDynamic,PcdsDynamicEx] + gPlatformModuleTokenSpaceGuid.PcdInConfigMode|FALSE|BOOLEAN|0x80000001 + gPlatformModuleTokenSpaceGuid.PcdConnectUSBKeyboardonWaitForKeyStroke|FALSE|BOOLEAN|0x80000002 + gPlatformModuleTokenSpaceGuid.PcdEnableWatchdogSwSmiInputValue|0|UINT8|0x80000003 +# +#device firmware update support +# +#I2C and SPI support +[Protocols] + + gEfiMmioDeviceProtocolGuid = { 0x24486226, 0xf8c2, 0x41f5, { 0xb9, 0xdd, 0x78, 0x3e, 0x9e, 0x56, 0xde, 0xa0 } } + gEfiI2cBusConfigurationManagementProtocolGuid = { 0x75032015, 0xd156, 0x423e, { 0xbf, 0xa3, 0x7a, 0x65, 0xab, 0xa4, 0x71, 0x5 } } + gEfiI2cAcpiProtocolGuid = { 0xf30c2915, 0x5782, 0x4e6a, { 0xa8, 0x46, 0x5, 0xba, 0xbc, 0xe7, 0xb6, 0xa0 } } + gEfiI2cMasterProtocolGuid = { 0x578c315a, 0x68cf, 0x4e81, { 0xb5, 0xc6, 0x22, 0xdb, 0x40, 0xd0, 0x10, 0xbc } } + gEfiI2cHostProtocolGuid = { 0x70b221af, 0xfdff, 0x4fde, { 0x99, 0x68, 0x1a, 0xf6, 0x23, 0xa9, 0x56, 0xd9 } } + gEfiI2cBusProtocolGuid = { 0x9fa1b225, 0x3346, 0x461b, { 0xa0, 0x69, 0xed, 0x1, 0xb6, 0x73, 0xd2, 0x40 } } + gEfiI2cSlaveProtocolGuid = { 0xf2c1910e, 0xf5c9, 0x4b72, { 0xb2, 0x43, 0x6d, 0x59, 0x9, 0x6a, 0x79, 0xf0 } } + +# gEfiSpiAcpiProtocolGuid = { 0x9f49a879, 0x3d71, 0x42b3, { 0xa0, 0xad, 0xdd, 0xb1, 0xf3, 0x30, 0x10, 0xa3 } } +# gEfiSpiHostProtocolGuid = { 0x951b65e5, 0x8872, 0x41ed, { 0xad, 0x1d, 0xd5, 0x68, 0x1f, 0x4a, 0xf0, 0x33 } } +# gEfiSpiBusProtocolGuid = { 0x137b3044, 0xf6d7, 0x473e, { 0xa6, 0x25, 0x9f, 0xb9, 0x25, 0x5, 0xc1, 0x80 } } + +# gLpssDummyProtocolGuid = { 0xaf4cc162, 0xd41c, 0x455a, { 0xab, 0x45, 0x6d, 0xbc, 0xc1, 0xcd, 0x32, 0xf3 } } + gEfiSpiProtocolGuid = { 0x1156efc6, 0xea32, 0x4396, { 0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13 }} + gEfiGpioOperationProtocolGuid = { 0x38DDFE8F, 0x8991, 0x44AA, { 0x98, 0x89, 0x83, 0xF4, 0x91, 0x84, 0x65, 0xB0 }} + gEfiEsrtOperationProtocolGuid = { 0x4549AB47, 0x6E60, 0x4293, { 0xB9, 0x1D, 0x31, 0xB6, 0x10, 0xAD, 0x80, 0x56 }} + +[Guids] + gEfiFwDisplayCapsuleGuid = { 0x3b8c8162, 0x188c, 0x46a4, { 0xae, 0xc9, 0xbe, 0x43, 0xf1, 0xd6, 0x56, 0x97 } } + gEfiFirmwareClassGuid = { 0xb122a262, 0x3551, 0x4f48, { 0x88, 0x92, 0x55, 0xf6, 0xc0, 0x61, 0x42, 0x90 } } + gEfiDFUVerGuid = { 0x0dc73aed, 0xcbf6, 0x4a25, { 0xa6, 0x8d, 0x59, 0xc8, 0x0f, 0x44, 0xc7, 0xc3 } } + gEfiEsrtTableGuid = { 0xb122a263, 0x3661, 0x4f68, { 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 } } + gEfiCapsuleCrashLogVarGuid = { 0xf3ff1468, 0x04ba, 0x4966, { 0x9f, 0xb2, 0xe4, 0xa7, 0x90, 0x05, 0x46, 0x50 } } + gEfiCapsuleCrashGuid = { 0x0e1d2972, 0x65af, 0x4ac1, { 0xbf, 0xa3, 0xce, 0xf4, 0xab, 0x0c, 0x38, 0xfe } } diff --git a/Vlv2TbltDevicePkg/PlatformPkg.fdf b/Vlv2TbltDevicePkg/PlatformPkg.fdf new file mode 100644 index 0000000000..f7c04e5cad --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPkg.fdf @@ -0,0 +1,1105 @@ +#/** @file +# FDF file of Platform. +# +# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] +DEFINE FLASH_BASE = 0xFFD00000 #The base address of the 3Mb FLASH Device. +DEFINE FLASH_SIZE = 0x00300000 #The flash size in bytes of the 3Mb FLASH Device. +DEFINE FLASH_BLOCK_SIZE = 0x1000 #The block size in bytes of the 3Mb FLASH Device. +DEFINE FLASH_NUM_BLOCKS = 0x300 #The number of blocks in 3Mb FLASH Device. +DEFINE FLASH_AREA_BASE_ADDRESS = 0xFF800000 +DEFINE FLASH_AREA_SIZE = 0x00800000 + + +DEFINE FLASH_REGION_VPD_OFFSET = 0x00000000 +DEFINE FLASH_REGION_VPD_SIZE = 0x0003E000 + +DEFINE FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_WORKING_OFFSET = 0x0003E000 +DEFINE FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_WORKING_SIZE = 0x00002000 + + +DEFINE FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_SPARE_OFFSET = 0x00040000 +DEFINE FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_SPARE_SIZE = 0x00040000 + +!if $(MINNOW2_FSP_BUILD) == TRUE +DEFINE FLASH_REGION_FSPBIN_OFFSET = 0x000B0000 +DEFINE FLASH_REGION_FSPBIN_SIZE = 0x00048000 +DEFINE FLASH_REGION_FSPBIN_BASE = 0xFFDB0000 + +DEFINE FLASH_REGION_AZALIABIN_OFFSET = 0x000F8000 +DEFINE FLASH_REGION_AZALIABIN_SIZE = 0x00008000 +DEFINE FLASH_REGION_AZALIABIN_BASE = 0xFFDF8000 + +!endif + +DEFINE FLASH_REGION_VLVMICROCODE_OFFSET = 0x00100000 +DEFINE FLASH_REGION_VLVMICROCODE_SIZE = 0x00030000 +DEFINE FLASH_REGION_VLVMICROCODE_BASE = 0xFFE00000 + +!if $(TARGET) == RELEASE +DEFINE FLASH_REGION_FVMAIN_OFFSET = 0x00170000 +DEFINE FLASH_REGION_FVMAIN_SIZE = 0x0012d000 +!else +!if $(SOURCE_DEBUG_ENABLE) == TRUE +DEFINE FLASH_REGION_FVMAIN_OFFSET = 0x00130000 +DEFINE FLASH_REGION_FVMAIN_SIZE = 0x00176000 +!else +DEFINE FLASH_REGION_FVMAIN_OFFSET = 0x00140000 +DEFINE FLASH_REGION_FVMAIN_SIZE = 0x00166000 +!endif +!endif + +!if $(TARGET) == RELEASE +DEFINE FLASH_REGION_FV_RECOVERY2_OFFSET = 0x0029d000 +DEFINE FLASH_REGION_FV_RECOVERY2_SIZE = 0x00021000 + +DEFINE FLASH_REGION_FV_RECOVERY_OFFSET = 0x002D0000 +DEFINE FLASH_REGION_FV_RECOVERY_SIZE = 0x00030000 +!else + +!if $(SOURCE_DEBUG_ENABLE) == TRUE +DEFINE FLASH_REGION_FV_RECOVERY2_OFFSET = 0x002A6000 +DEFINE FLASH_REGION_FV_RECOVERY2_SIZE = 0x0002D000 +!else +DEFINE FLASH_REGION_FV_RECOVERY2_OFFSET = 0x002A6000 +DEFINE FLASH_REGION_FV_RECOVERY2_SIZE = 0x0002D000 +!endif + + +DEFINE FLASH_REGION_FV_RECOVERY_OFFSET = 0x002D3000 +DEFINE FLASH_REGION_FV_RECOVERY_SIZE = 0x0002D000 +!endif + +################################################################################ +# +# 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.Vlv] +BaseAddress = $(FLASH_BASE)|gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress #The base address of the 3Mb FLASH Device. +Size = $(FLASH_SIZE)|gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize #The flash size in bytes of the 3Mb FLASH Device. +ErasePolarity = 1 +BlockSize = $(FLASH_BLOCK_SIZE) #The block size in bytes of the 3Mb FLASH Device. +NumBlocks = $(FLASH_NUM_BLOCKS) #The number of blocks in 3Mb FLASH Device. + +# +#Flash location override based on actual flash map +# +SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress = $(FLASH_AREA_BASE_ADDRESS) +SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize = $(FLASH_AREA_SIZE) + +!if $(MINNOW2_FSP_BUILD) == TRUE +# put below PCD value setting into dsc file +#SET gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchAddress = $(FLASH_REGION_VLVMICROCODE_BASE) +#SET gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize = $(FLASH_REGION_VLVMICROCODE_SIZE) +#SET gFspWrapperTokenSpaceGuid.PcdFlashMicroCodeOffset = 0x60 +#SET gFspWrapperTokenSpaceGuid.PcdFlashCodeCacheAddress = $(FLASH_AREA_BASE_ADDRESS) +#SET gFspWrapperTokenSpaceGuid.PcdFlashCodeCacheSize = $(FLASH_AREA_SIZE) +#SET gFspWrapperTokenSpaceGuid.PcdFlashFvFspBase = $(FLASH_REGION_FSPBIN_BASE) +#SET gFspWrapperTokenSpaceGuid.PcdFlashFvFspSize = $(FLASH_REGION_FSPBIN_SIZE) + +!endif +################################################################################ +# +# 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 Size can be adjusted; FVMAIN_COMPACT can be reduced to 0x120000, and FV_RECOVERY can be enlarged to 0x80000 +# +################################################################################ +$(FLASH_REGION_VPD_OFFSET)|$(FLASH_REGION_VPD_SIZE) +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: 0x80000 + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + #Signature "_FVH" #Attributes + 0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00, + #HeaderLength #CheckSum #ExtHeaderOffset #Reserved #Revision + 0x48, 0x00, 0x2A, 0x09, 0x00, 0x00, 0x00, 0x02, + #Blockmap[0]: 7 Blocks * 0x10000 Bytes / Block + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + #Blockmap[1]: End + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ## This is the VARIABLE_STORE_HEADER +!if $(SECURE_BOOT_ENABLE) == TRUE + #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: 0x3E000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) - 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0x03DFB8 + # This can speed up the Variable Dispatch a bit. + 0xB8, 0xDF, 0x03, 0x00, + #FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32 + 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} + + +$(FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_WORKING_OFFSET)|$(FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_WORKING_SIZE) +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize +#NV_FTW_WORKING +DATA = { + # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid = + # { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95 }} + 0x2B, 0x29, 0x58, 0x9E, 0x68, 0x7C, 0x7D, 0x49, + 0xA0, 0xCE, 0x65, 0x0, 0xFD, 0x9F, 0x1B, 0x95, + + # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved + 0xE2, 0x33, 0xF2, 0x3, 0xFE, 0xFF, 0xFF, 0xFF, + # WriteQueueSize: UINT64 #Size: 0x2000 - 0x20 (FTW_WORKING_HEADER) = 0x1FE0 + 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} + +$(FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_SPARE_OFFSET)|$(FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_SPARE_SIZE) +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + +!if $(MINNOW2_FSP_BUILD) == TRUE + + $(FLASH_REGION_FSPBIN_OFFSET)|$(FLASH_REGION_FSPBIN_SIZE) + gFspWrapperTokenSpaceGuid.PcdFlashFvFspBase|gFspWrapperTokenSpaceGuid.PcdFlashFvFspSize + FILE = Vlv2MiscBinariesPkg/FspBinary/FvFsp.bin + + + $(FLASH_REGION_AZALIABIN_OFFSET)|$(FLASH_REGION_AZALIABIN_SIZE) + FILE = Vlv2TbltDevicePkg/FspAzaliaConfigData/AzaliaConfig.bin + +!endif + # + # CPU Microcodes + # + +$(FLASH_REGION_VLVMICROCODE_OFFSET)|$(FLASH_REGION_VLVMICROCODE_SIZE) +gPlatformModuleTokenSpaceGuid.PcdFlashMicroCodeAddress|gPlatformModuleTokenSpaceGuid.PcdFlashMicroCodeSize +FV = MICROCODE_FV + + # + # Main Block + # +$(FLASH_REGION_FVMAIN_OFFSET)|$(FLASH_REGION_FVMAIN_SIZE) +gPlatformModuleTokenSpaceGuid.PcdFlashFvMainBase|gPlatformModuleTokenSpaceGuid.PcdFlashFvMainSize +FV = FVMAIN_COMPACT + + # + # FV Recovery#2 + # +$(FLASH_REGION_FV_RECOVERY2_OFFSET)|$(FLASH_REGION_FV_RECOVERY2_SIZE) +gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Base|gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Size +FV = FVRECOVERY2 + + # + # FV Recovery + # +$(FLASH_REGION_FV_RECOVERY_OFFSET)|$(FLASH_REGION_FV_RECOVERY_SIZE) +gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoveryBase|gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoverySize +FV = FVRECOVERY + +################################################################################ +# +# 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.MICROCODE_FV] +BlockSize = $(FLASH_BLOCK_SIZE) +FvAlignment = 16 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = FALSE +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 RAW = 197DB236-F856-4924-90F8-CDF12FB875F3 { + $(OUTPUT_DIRECTORY)\$(TARGET)_$(TOOL_CHAIN_TAG)\$(DXE_ARCHITECTURE)\MicrocodeUpdates.bin +} + +################################################################################ +# +# 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.FVRECOVERY2] +BlockSize = $(FLASH_BLOCK_SIZE) +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 = B73FE497-B92E-416e-8326-45AD0D270092 + + + +INF $(PLATFORM_PACKAGE)/PlatformInitPei/PlatformInitPei.inf + +!if $(MINNOW2_FSP_BUILD) == FALSE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchSmbusArpDisabled.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/VlvInitPeim.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchInitPeim.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchSpiPeim.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PeiSmmAccess.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PeiSmmControl.inf +INF UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf +INF EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf +!endif + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf +!if $(TPM_ENABLED) == TRUE +INF SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf +INF SecurityPkg/Tcg/TcgPei/TcgPei.inf +INF SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf +!endif +INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf + +!if $(ACPI50_ENABLE) == TRUE + INF MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf +!endif +!if $(PERFORMANCE_ENABLE) == TRUE +INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf +!endif + +[FV.FVRECOVERY] +BlockSize = $(FLASH_BLOCK_SIZE) +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 = B73FE497-B92E-416e-8326-45AD0D270091 + + +!if $(MINNOW2_FSP_BUILD) == TRUE +INF IntelFspWrapperPkg/FspWrapperSecCore/FspWrapperSecCore.inf +!else +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf +!endif + +INF MdeModulePkg/Core/Pei/PeiMain.inf +!if $(MINNOW2_FSP_BUILD) == TRUE +INF Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.inf +INF IntelFspWrapperPkg/FspInitPei/FspInitPei.inf +!endif +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/CpuPeim.inf +INF MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf +!if $(SECURE_BOOT_ENABLE) == TRUE +INF SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf +!else +INF MdeModulePkg/Universal/Variable/Pei/VariablePei.inf +!endif + +INF $(PLATFORM_PACKAGE)/PlatformPei/PlatformPei.inf + +!if $(MINNOW2_FSP_BUILD) == FALSE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SeCUma.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + INF SourceLevelDebugPkg/DebugAgentPei/DebugAgentPei.inf +!endif + + +!if $(CAPSULE_ENABLE) == TRUE +INF MdeModulePkg/Universal/CapsulePei/CapsulePei.inf +INF MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf +!endif + +!if $(MINNOW2_FSP_BUILD) == FALSE +!if $(PCIESC_ENABLE) == TRUE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchEarlyInitPeim.inf +!endif +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MemoryInit.inf +!endif + +INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf + +[FV.FVMAIN] +BlockSize = $(FLASH_BLOCK_SIZE) +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 = A881D567-6CB0-4eee-8435-2E72D33E45B5 + +APRIORI DXE { + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf + } + +FILE FREEFORM = C3E36D09-8294-4b97-A857-D5288FE33E28 { + SECTION RAW = $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/$(DXE_ARCHITECTURE)/BiosId.bin + } + + # + # EDK II Related Platform codes + # + + !if $(MINNOW2_FSP_BUILD) == TRUE + INF IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.inf + !endif + +INF MdeModulePkg/Core/Dxe/DxeMain.inf +INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf +!if $(ACPI50_ENABLE) == TRUE +INF MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf +INF MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf +!endif + + +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/SecurityStubDxe/SecurityStubDxe.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MpCpu.inf +INF $(PLATFORM_PACKAGE)/Metronome/Metronome.inf +INF IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf +INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf +INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf +INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf +INF IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf + +!if $(SECURE_BOOT_ENABLE) +INF SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf +INF SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf +INF $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbSmm.inf +INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiSmm.inf +INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +!else +INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf +INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf +INF $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbSmm.inf +INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiSmm.inf +!endif + +INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + +INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf +INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf +INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf +INF $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbRuntimeDxe.inf + + +INF $(PLATFORM_PACKAGE)/PlatformSetupDxe/PlatformSetupDxe.inf + +!if $(DATAHUB_ENABLE) == TRUE +INF IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf +!endif +INF IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf +INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/Dptf.inf + + # + # EDK II Related Silicon codes + # +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchS3SupportDxe.inf + +!if $(USE_HPET_TIMER) == TRUE +INF PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf +!else +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmartTimer.inf +!endif +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmmControl.inf + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSmbusDxe.inf + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/IntelPchLegacyInterrupt.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchReset.inf + +!if $(MINNOW2_FSP_BUILD) == FALSE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchInitDxe.inf +!endif +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSmiDispatcher.inf +!if $(PCIESC_ENABLE) == TRUE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchPcieSmm.inf +!endif + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiRuntime.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchPolicyInitDxe.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchBiosWriteProtect.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmmAccess.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PciHostBridge.inf +!if $(MINNOW2_FSP_BUILD) == FALSE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/VlvInitDxe.inf +!else +INF IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf +INF Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInitDxe.inf +!endif +!if $(TPM_ENABLED) == TRUE +INF SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf +INF SecurityPkg/Tcg/TcgDxe/TcgDxe.inf +INF RuleOverride = DRIVER_ACPITABLE SecurityPkg/Tcg/TcgSmm/TcgSmm.inf +!endif + +# +# EDK II Related Platform codes +# +INF $(PLATFORM_PACKAGE)/PlatformSmm/PlatformSmm.inf +INF $(PLATFORM_PACKAGE)/PlatformInfoDxe/PlatformInfoDxe.inf +INF $(PLATFORM_PACKAGE)/PlatformCpuInfoDxe/PlatformCpuInfoDxe.inf +INF $(PLATFORM_PACKAGE)/PlatformDxe/PlatformDxe.inf +INF $(PLATFORM_PACKAGE)/PciPlatform/PciPlatform.inf +INF $(PLATFORM_PACKAGE)/SaveMemoryConfig/SaveMemoryConfig.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PlatformCpuPolicy.inf +INF $(PLATFORM_PACKAGE)/PpmPolicy/PpmPolicy.inf +INF $(PLATFORM_PACKAGE)/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.inf +!if $(GOP_DRIVER_ENABLE) == TRUE + INF $(PLATFORM_PACKAGE)/PlatformGopPolicy/PlatformGopPolicy.inf + FILE DRIVER = FF0C8745-3270-4439-B74F-3E45F8C77064 { + SECTION DXE_DEPEX_EXP = {gPlatformGOPPolicyGuid} + SECTION PE32 = Vlv2MiscBinariesPkg/GOP/7.2.1011/RELEASE_VS2008x86/$(DXE_ARCHITECTURE)/IntelGopDriver.efi + SECTION UI = "IntelGopDriver" +} +!endif + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PnpDxe.inf + # + # SMM + # +INF MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf +INF MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PiSmmCpuDxeSmm.inf + +INF UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf +INF MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PiSmmCommunicationSmm.inf +INF $(PLATFORM_PACKAGE)/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PowerManagement2.inf +# INF Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Dts/Smm/DigitalThermalSensor.inf + # + # ACPI + # +INF MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf +INF $(PLATFORM_PACKAGE)/BootScriptSaveDxe/BootScriptSaveDxe.inf +INF IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf +INF RuleOverride = ACPITABLE2 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/PowerManagementAcpiTables.inf + +INF RuleOverride = ACPITABLE $(PLATFORM_RC_PACKAGE)/AcpiTablesPCAT/AcpiTables.inf + +INF $(PLATFORM_PACKAGE)/AcpiPlatform/AcpiPlatform.inf + + # + # PCI + # +INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/ISPDxe.inf + + +# +# ISA +# +INF $(PLATFORM_PACKAGE)/Wpce791/Wpce791.inf +INF IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf +INF IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf +!if $(SOURCE_DEBUG_ENABLE) != TRUE +INF IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf +!endif +INF IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf +INF IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf + +# +# SDIO +# +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MmcHost.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MmcMediaDevice.inf +# +# IDE/SCSI/AHCI +# +INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + +INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + +INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf +!if $(SATA_ENABLE) == TRUE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SataController.inf +# + +# +INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf +!if $(SCSI_ENABLE) == TRUE +INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf +INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf +!endif +# +!endif +# Console +# +INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf +INF Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf +INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf +INF IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf +INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf +INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf +INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + # + # USB + # +!if $(USB_ENABLE) == TRUE +INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf +INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf +INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf +INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf +INF MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf +INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf +INF MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf +!endif + + # + # ECP + # +INF EdkCompatibilityPkg/Compatibility/LegacyRegion2OnLegacyRegionThunk/LegacyRegion2OnLegacyRegionThunk.inf +INF EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.inf +INF EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.inf +INF EdkCompatibilityPkg/Compatibility/SmmAccess2OnSmmAccessThunk/SmmAccess2OnSmmAccessThunk.inf +INF EdkCompatibilityPkg/Compatibility/SmmControl2OnSmmControlThunk/SmmControl2OnSmmControlThunk.inf +INF EdkCompatibilityPkg/Compatibility/FvOnFv2Thunk/FvOnFv2Thunk.inf + # + # SMBIOS + # +INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf +INF $(PLATFORM_PACKAGE)/SmBiosMiscDxe/SmBiosMiscDxe.inf + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmbiosMemory.inf + + # + # Legacy Modules + # +INF PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf + +# +# FAT file system +# +FILE DRIVER = 961578FE-B6B7-44c3-AF35-6BC705CD2B1F { + SECTION PE32 = FatBinPkg/EnhancedFatDxe/$(EDK_DXE_ARCHITECTURE)/Fat.efi + } +# +# UEFI Shell +# +FILE APPLICATION = PCD(gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile) { + SECTION PE32 = EdkShellBinPkg/FullShell/$(EDK_DXE_ARCHITECTURE)/Shell_Full.efi + } + + + +!if $(GOP_DRIVER_ENABLE) == TRUE +FILE FREEFORM = 878AC2CC-5343-46F2-B563-51F89DAF56BA { + SECTION RAW = Vlv2MiscBinariesPkg/GOP/7.2.1011/VBT/MNW2/Vbt.bin + SECTION UI = "IntelGopVbt" +} +!endif + +# +# Network Modules +# +!if $(NETWORK_ENABLE) == TRUE + FILE DRIVER = 22DE1691-D65D-456a-993E-A253DD1F308C { + SECTION PE32 = Vlv2MiscBinariesPkg/UNDI/RtkUndiDxe/$(DXE_ARCHITECTURE)/RtkUndiDxe.efi + SECTION UI = "UNDI" + } + INF MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf + INF MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf + INF MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf + INF MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf + INF MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf + INF MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf + INF MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf + INF MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf + INF MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf + !if $(NETWORK_IP6_ENABLE) == TRUE + INF NetworkPkg/Ip6Dxe/Ip6Dxe.inf + INF NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf + INF NetworkPkg/IpSecDxe/IpSecDxe.inf + INF NetworkPkg/Udp6Dxe/Udp6Dxe.inf + INF NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf + !endif + !if $(NETWORK_IP6_ENABLE) == TRUE + INF NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf + INF NetworkPkg/TcpDxe/TcpDxe.inf + !else + INF MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf + INF MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf + !endif + !if $(NETWORK_VLAN_ENABLE) == TRUE + INF MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf + !endif + !if $(NETWORK_ISCSI_ENABLE) == TRUE + !if $(NETWORK_IP6_ENABLE) == TRUE + INF NetworkPkg/IScsiDxe/IScsiDxe.inf + !else + INF MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf + !endif + !endif +!endif + +[FV.FVMAIN_COMPACT] +BlockSize = $(FLASH_BLOCK_SIZE) +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 { +!if $(LZMA_ENABLE) == TRUE +# LZMA Compress + SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + SECTION FV_IMAGE = FVMAIN + } +!else +!if $(DXE_COMPRESS_ENABLE) == TRUE +# Tiano Compress + SECTION GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE { + SECTION FV_IMAGE = FVMAIN + } +!else +# No Compress + SECTION COMPRESS PI_NONE { + SECTION FV_IMAGE = FVMAIN + } +!endif +!endif + } + +[FV.SETUP_DATA] +BlockSize = $(FLASH_BLOCK_SIZE) +#NumBlocks = 0x10 +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 + + +[FV.Update_Data] +BlockSize = $(FLASH_BLOCK_SIZE) +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 RAW = 88888888-8888-8888-8888-888888888888 { + FD = Vlv + } + +[FV.BiosUpdateCargo] +BlockSize = $(FLASH_BLOCK_SIZE) +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 + + + +[FV.BiosUpdate] +BlockSize = $(FLASH_BLOCK_SIZE) +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 + +[Capsule.Capsule_Boot] +# +# gEfiCapsuleGuid supported by platform +# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }} +# +CAPSULE_GUID = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0 +CAPSULE_FLAGS = PersistAcrossReset +CAPSULE_HEADER_SIZE = 0x20 + +FV = BiosUpdate + +[Capsule.Capsule_Reset] +# +# gEfiCapsuleGuid supported by platform +# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }} +# +CAPSULE_GUID = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0 +CAPSULE_FLAGS = PersistAcrossReset +CAPSULE_HEADER_SIZE = 0x20 + +FV = BiosUpdate + +################################################################################ +# +# 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 { + PE32 PE32 Align = 8 $(INF_OUTPUT)/$(MODULE_NAME).efi + RAW BIN Align = 16 |.com + } + +[Rule.Common.SEC.BINARY] + FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED { + PE32 PE32 Align = 8 |.efi + RAW BIN Align = 16 |.com + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + PE32 PE32 Align = Auto $(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 + PE32 PE32 Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.PEIM.BINARY] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional |.depex + PE32 PE32 Align = Auto |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.PEIM.BIOSID] + FILE PEIM = $(NAMED_GUID) { + RAW BIN BiosId.bin + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.USER_DEFINED.APINIT] + FILE RAW = $(NAMED_GUID) Fixed Align=4K { + RAW SEC_BIN |.com + } +#cjia 2011-07-21 +[Rule.Common.USER_DEFINED.LEGACY16] + FILE FREEFORM = $(NAMED_GUID) { + UI STRING="$(MODULE_NAME)" Optional + RAW BIN |.bin + } +#cjia + +[Rule.Common.USER_DEFINED.ASM16] + FILE FREEFORM = $(NAMED_GUID) { + UI STRING="$(MODULE_NAME)" Optional + RAW BIN |.com + } + +[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.UEFI_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_DRIVER.NATIVE_BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(WORKSPACE)/$(PLATFORM_PACKAGE)/IntelGopDepex/IntelGopDriver.depex + PE32 PE32 |.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_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_DRIVER.DRIVER_ACPITABLE] + 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) + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml + } + +[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_RUNTIME_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_SMM_DRIVER] + FILE SMM = $(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.BINARY] + FILE SMM = $(NAMED_GUID) { + SMM_DEPEX SMM_DEPEX |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_SMM_DRIVER.DRIVER_ACPITABLE] + FILE SMM = $(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) + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml + } + +[Rule.Common.SMM_CORE] + FILE SMM_CORE = $(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.SMM_CORE.BINARY] + FILE SMM_CORE = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(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.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] + FILE FREEFORM = $(NAMED_GUID) { + UI STRING="$(MODULE_NAME)" Optional + RAW BIN |.bin + } + +[Rule.Common.USER_DEFINED.ACPITABLE] + FILE FREEFORM = $(NAMED_GUID) { + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml + } + +[Rule.Common.USER_DEFINED.ACPITABLE2] + FILE FREEFORM = $(NAMED_GUID) { + RAW ASL Optional |.aml + } + +[Rule.Common.ACPITABLE] + FILE FREEFORM = $(NAMED_GUID) { + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml + } + diff --git a/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc b/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc new file mode 100644 index 0000000000..ec24fed407 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPkgConfig.dsc @@ -0,0 +1,96 @@ +#/** @file +# platform configuration file. +# +# Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +# +# TRUE is ENABLE. FASLE is DISABLE. +# + +# +# FSP selection +# +DEFINE MINNOW2_FSP_BUILD = FALSE + + +DEFINE SCSI_ENABLE = TRUE + + +# +# To enable extra configuration for clk gen +# +DEFINE CLKGEN_CONFIG_EXTRA_ENABLE=TRUE + +# +# Feature selection +# + +# +# Select system timer which is used to produce Timer Arch Protocol: +# TRUE - HPET timer is used. +# FALSE - 8254 timer is used. +# +DEFINE USE_HPET_TIMER = FALSE + +# +# Feature selection +# + +DEFINE TPM_ENABLED = FALSE + +DEFINE ACPI50_ENABLE = TRUE +DEFINE PERFORMANCE_ENABLE = FALSE + + +DEFINE LFMA_ENABLE = FALSE # Load module at fixed address feature +DEFINE DXE_COMPRESS_ENABLE = TRUE +DEFINE DXE_CRC32_SECTION_ENABLE = TRUE +DEFINE SSE2_ENABLE = FALSE + +DEFINE SECURE_BOOT_ENABLE = TRUE +DEFINE USER_IDENTIFICATION_ENABLE = FALSE +DEFINE VARIABLE_INFO_ENABLE = FALSE +DEFINE S3_ENABLE = TRUE +DEFINE CAPSULE_ENABLE = FALSE +DEFINE CAPSULE_RESET_ENABLE = TRUE + +DEFINE GOP_DRIVER_ENABLE = TRUE +DEFINE DATAHUB_ENABLE = TRUE +DEFINE DATAHUB_STATUS_CODE_ENABLE = TRUE +DEFINE USB_ENABLE = TRUE + +DEFINE ISA_SERIAL_STATUS_CODE_ENABLE = TRUE +DEFINE USB_SERIAL_STATUS_CODE_ENABLE = FALSE +DEFINE RAM_SERIAL_STATUS_CODE_ENABLE = FALSE + +DEFINE ENBDT_S3_SUPPORT = TRUE + +DEFINE LZMA_ENABLE = TRUE +DEFINE S4_ENABLE = TRUE +DEFINE NETWORK_ENABLE = TRUE +DEFINE NETWORK_IP6_ENABLE = TRUE +DEFINE NETWORK_ISCSI_ENABLE = FALSE +DEFINE NETWORK_VLAN_ENABLE = FALSE + +DEFINE SATA_ENABLE = TRUE +DEFINE PCIESC_ENABLE = TRUE + +# +# Enable source level debug default +# +DEFINE SOURCE_DEBUG_ENABLE = FALSE + + + + diff --git a/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf b/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf new file mode 100644 index 0000000000..a9f62dc89a --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPkgGcc.fdf @@ -0,0 +1,1037 @@ +#/** @file +# FDF file of Platform. +# +# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] +DEFINE FLASH_BASE = 0xFFD00000 #The base address of the 3Mb FLASH Device. +DEFINE FLASH_SIZE = 0x00300000 #The flash size in bytes of the 3Mb FLASH Device. +DEFINE FLASH_BLOCK_SIZE = 0x1000 #The block size in bytes of the 3Mb FLASH Device. +DEFINE FLASH_NUM_BLOCKS = 0x300 #The number of blocks in 3Mb FLASH Device. +DEFINE FLASH_AREA_BASE_ADDRESS = 0xFF800000 +DEFINE FLASH_AREA_SIZE = 0x00800000 + + +DEFINE FLASH_REGION_VPD_OFFSET = 0x00000000 +DEFINE FLASH_REGION_VPD_SIZE = 0x0003E000 + +DEFINE FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_WORKING_OFFSET = 0x0003E000 +DEFINE FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_WORKING_SIZE = 0x00002000 + + +DEFINE FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_SPARE_OFFSET = 0x00040000 +DEFINE FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_SPARE_SIZE = 0x00040000 + +!if $(MINNOW2_FSP_BUILD) == TRUE +DEFINE FLASH_REGION_FSPBIN_OFFSET = 0x000B0000 +DEFINE FLASH_REGION_FSPBIN_SIZE = 0x00048000 +DEFINE FLASH_REGION_FSPBIN_BASE = 0xFFDB0000 + +DEFINE FLASH_REGION_AZALIABIN_OFFSET = 0x000F8000 +DEFINE FLASH_REGION_AZALIABIN_SIZE = 0x00008000 +DEFINE FLASH_REGION_AZALIABIN_BASE = 0xFFDF8000 + +!endif + +DEFINE FLASH_REGION_VLVMICROCODE_OFFSET = 0x00100000 +DEFINE FLASH_REGION_VLVMICROCODE_SIZE = 0x00030000 +DEFINE FLASH_REGION_VLVMICROCODE_BASE = 0xFFE00000 + +DEFINE FLASH_REGION_FVMAIN_OFFSET = 0x00130000 +DEFINE FLASH_REGION_FVMAIN_SIZE = 0x0016C000 + + +DEFINE FLASH_REGION_FV_RECOVERY2_OFFSET = 0x0029C000 +DEFINE FLASH_REGION_FV_RECOVERY2_SIZE = 0x0002F000 + +DEFINE FLASH_REGION_FV_RECOVERY_OFFSET = 0x002CB000 +DEFINE FLASH_REGION_FV_RECOVERY_SIZE = 0x00035000 + +################################################################################ +# +# 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.Vlv] +BaseAddress = $(FLASH_BASE)|gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress #The base address of the 3Mb FLASH Device. +Size = $(FLASH_SIZE)|gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize #The flash size in bytes of the 3Mb FLASH Device. +ErasePolarity = 1 +BlockSize = $(FLASH_BLOCK_SIZE) #The block size in bytes of the 3Mb FLASH Device. +NumBlocks = $(FLASH_NUM_BLOCKS) #The number of blocks in 3Mb FLASH Device. + +# +#Flash location override based on actual flash map +# +SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress = $(FLASH_AREA_BASE_ADDRESS) +SET gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize = $(FLASH_AREA_SIZE) + +!if $(MINNOW2_FSP_BUILD) == TRUE +# put below PCD value setting into dsc file +#SET gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchAddress = $(FLASH_REGION_VLVMICROCODE_BASE) +#SET gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize = $(FLASH_REGION_VLVMICROCODE_SIZE) +#SET gFspWrapperTokenSpaceGuid.PcdFlashMicroCodeOffset = 0x60 +#SET gFspWrapperTokenSpaceGuid.PcdFlashCodeCacheAddress = $(FLASH_AREA_BASE_ADDRESS) +#SET gFspWrapperTokenSpaceGuid.PcdFlashCodeCacheSize = $(FLASH_AREA_SIZE) +#SET gFspWrapperTokenSpaceGuid.PcdFlashFvFspBase = $(FLASH_REGION_FSPBIN_BASE) +#SET gFspWrapperTokenSpaceGuid.PcdFlashFvFspSize = $(FLASH_REGION_FSPBIN_SIZE) + +!endif +################################################################################ +# +# 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 Size can be adjusted; FVMAIN_COMPACT can be reduced to 0x120000, and FV_RECOVERY can be enlarged to 0x80000 +# +################################################################################ +# Since the Fce tool don't have gcc version, we can't handle default variable in Linux, +# so we hardcode the default value of variable here. +# Please note that we MUST update the binary once the default value is changed. +$(FLASH_REGION_VPD_OFFSET)|$(FLASH_REGION_VPD_SIZE) +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize +FILE = $(WORKSPACE)/Vlv2TbltDevicePkg/Stitch/Gcc/NvStorageVariable.bin + +$(FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_WORKING_OFFSET)|$(FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_WORKING_SIZE) +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize +FILE = $(WORKSPACE)/Vlv2TbltDevicePkg/Stitch/Gcc/NvStorageFtwWorking.bin + +$(FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_SPARE_OFFSET)|$(FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_SPARE_SIZE) +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize +FILE = $(WORKSPACE)/Vlv2TbltDevicePkg/Stitch/Gcc/NvStorageFtwSpare.bin + +!if $(MINNOW2_FSP_BUILD) == TRUE + + $(FLASH_REGION_FSPBIN_OFFSET)|$(FLASH_REGION_FSPBIN_SIZE) + gFspWrapperTokenSpaceGuid.PcdFlashFvFspBase|gFspWrapperTokenSpaceGuid.PcdFlashFvFspSize + FILE = Vlv2MiscBinariesPkg/FspBinary/FvFsp.bin + + + $(FLASH_REGION_AZALIABIN_OFFSET)|$(FLASH_REGION_AZALIABIN_SIZE) + FILE = Vlv2TbltDevicePkg/FspAzaliaConfigData/AzaliaConfig.bin + +!endif + # + # CPU Microcodes + # + +$(FLASH_REGION_VLVMICROCODE_OFFSET)|$(FLASH_REGION_VLVMICROCODE_SIZE) +gPlatformModuleTokenSpaceGuid.PcdFlashMicroCodeAddress|gPlatformModuleTokenSpaceGuid.PcdFlashMicroCodeSize +FV = MICROCODE_FV + + # + # Main Block + # +$(FLASH_REGION_FVMAIN_OFFSET)|$(FLASH_REGION_FVMAIN_SIZE) +gPlatformModuleTokenSpaceGuid.PcdFlashFvMainBase|gPlatformModuleTokenSpaceGuid.PcdFlashFvMainSize +FV = FVMAIN_COMPACT + + # + # FV Recovery#2 + # +$(FLASH_REGION_FV_RECOVERY2_OFFSET)|$(FLASH_REGION_FV_RECOVERY2_SIZE) +gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Base|gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Size +FV = FVRECOVERY2 + + # + # FV Recovery + # +$(FLASH_REGION_FV_RECOVERY_OFFSET)|$(FLASH_REGION_FV_RECOVERY_SIZE) +gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoveryBase|gPlatformModuleTokenSpaceGuid.PcdFlashFvRecoverySize +FV = FVRECOVERY + +################################################################################ +# +# 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.MICROCODE_FV] +BlockSize = $(FLASH_BLOCK_SIZE) +FvAlignment = 16 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = FALSE +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 RAW = 197DB236-F856-4924-90F8-CDF12FB875F3 { + $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/$(DXE_ARCHITECTURE)/MicrocodeUpdates.bin +} + +################################################################################ +# +# 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.FVRECOVERY2] +BlockSize = $(FLASH_BLOCK_SIZE) +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 = B73FE497-B92E-416e-8326-45AD0D270092 + + + +INF $(PLATFORM_PACKAGE)/PlatformInitPei/PlatformInitPei.inf + +!if $(MINNOW2_FSP_BUILD) == FALSE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchSmbusArpDisabled.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/VlvInitPeim.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchInitPeim.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchSpiPeim.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PeiSmmAccess.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PeiSmmControl.inf +INF UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf +INF EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf +!endif + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf +!if $(TPM_ENABLED) == TRUE +INF SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf +INF SecurityPkg/Tcg/TcgPei/TcgPei.inf +INF SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf +!endif +INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf + +!if $(ACPI50_ENABLE) == TRUE + INF MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf +!endif +!if $(PERFORMANCE_ENABLE) == TRUE +INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf +!endif + +[FV.FVRECOVERY] +BlockSize = $(FLASH_BLOCK_SIZE) +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 = B73FE497-B92E-416e-8326-45AD0D270091 + + +!if $(MINNOW2_FSP_BUILD) == TRUE +INF IntelFspWrapperPkg/FspWrapperSecCore/FspWrapperSecCore.inf +!else +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf +!endif + +INF MdeModulePkg/Core/Pei/PeiMain.inf +!if $(MINNOW2_FSP_BUILD) == TRUE +INF Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.inf +INF IntelFspWrapperPkg/FspInitPei/FspInitPei.inf +!endif +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/CpuPeim.inf +INF MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf +!if $(SECURE_BOOT_ENABLE) == TRUE +INF SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf +!else +INF MdeModulePkg/Universal/Variable/Pei/VariablePei.inf +!endif + +INF $(PLATFORM_PACKAGE)/PlatformPei/PlatformPei.inf + +!if $(MINNOW2_FSP_BUILD) == FALSE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SeCUma.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + INF SourceLevelDebugPkg/DebugAgentPei/DebugAgentPei.inf +!endif + + +!if $(CAPSULE_ENABLE) == TRUE +INF MdeModulePkg/Universal/CapsulePei/CapsulePei.inf +INF MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf +!endif + +!if $(MINNOW2_FSP_BUILD) == FALSE +!if $(PCIESC_ENABLE) == TRUE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchEarlyInitPeim.inf +!endif +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MemoryInit.inf +!endif + +INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf + +[FV.FVMAIN] +BlockSize = $(FLASH_BLOCK_SIZE) +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 = A881D567-6CB0-4eee-8435-2E72D33E45B5 + +APRIORI DXE { + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf + } + +FILE FREEFORM = C3E36D09-8294-4b97-A857-D5288FE33E28 { + SECTION RAW = $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/$(DXE_ARCHITECTURE)/BiosId.bin + } + + # + # EDK II Related Platform codes + # + + !if $(MINNOW2_FSP_BUILD) == TRUE + INF IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.inf + !endif + +INF MdeModulePkg/Core/Dxe/DxeMain.inf +INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf +!if $(ACPI50_ENABLE) == TRUE +INF MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf +INF MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf +!endif + + +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/SecurityStubDxe/SecurityStubDxe.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MpCpu.inf +INF $(PLATFORM_PACKAGE)/Metronome/Metronome.inf +INF IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf +INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf +INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf +INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf +INF IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf + +!if $(SECURE_BOOT_ENABLE) +INF SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf +INF SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf +INF $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbSmm.inf +INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiSmm.inf +INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +!else +INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf +INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf +INF $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbSmm.inf +INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiSmm.inf +!endif + +INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + +INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf +INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf +INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf +INF $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbRuntimeDxe.inf + + +INF $(PLATFORM_PACKAGE)/PlatformSetupDxe/PlatformSetupDxe.inf + +!if $(DATAHUB_ENABLE) == TRUE +INF IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf +!endif +INF IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf +INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/Dptf.inf + + # + # EDK II Related Silicon codes + # +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchS3SupportDxe.inf + +!if $(USE_HPET_TIMER) == TRUE +INF PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf +!else +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmartTimer.inf +!endif +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmmControl.inf + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSmbusDxe.inf + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/IntelPchLegacyInterrupt.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchReset.inf + +!if $(MINNOW2_FSP_BUILD) == FALSE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchInitDxe.inf +!endif +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSmiDispatcher.inf +!if $(PCIESC_ENABLE) == TRUE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchPcieSmm.inf +!endif + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiRuntime.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchPolicyInitDxe.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchBiosWriteProtect.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmmAccess.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PciHostBridge.inf +!if $(MINNOW2_FSP_BUILD) == FALSE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/VlvInitDxe.inf +!else +INF IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf +INF Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInitDxe.inf +!endif +!if $(TPM_ENABLED) == TRUE +INF SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf +INF SecurityPkg/Tcg/TcgDxe/TcgDxe.inf +INF RuleOverride = DRIVER_ACPITABLE SecurityPkg/Tcg/TcgSmm/TcgSmm.inf +!endif + +# +# EDK II Related Platform codes +# +INF $(PLATFORM_PACKAGE)/PlatformSmm/PlatformSmm.inf +INF $(PLATFORM_PACKAGE)/PlatformInfoDxe/PlatformInfoDxe.inf +INF $(PLATFORM_PACKAGE)/PlatformCpuInfoDxe/PlatformCpuInfoDxe.inf +INF $(PLATFORM_PACKAGE)/PlatformDxe/PlatformDxe.inf +INF $(PLATFORM_PACKAGE)/PciPlatform/PciPlatform.inf +INF $(PLATFORM_PACKAGE)/SaveMemoryConfig/SaveMemoryConfig.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PlatformCpuPolicy.inf +INF $(PLATFORM_PACKAGE)/PpmPolicy/PpmPolicy.inf +INF $(PLATFORM_PACKAGE)/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.inf +!if $(GOP_DRIVER_ENABLE) == TRUE + INF $(PLATFORM_PACKAGE)/PlatformGopPolicy/PlatformGopPolicy.inf + FILE DRIVER = FF0C8745-3270-4439-B74F-3E45F8C77064 { + SECTION DXE_DEPEX_EXP = {gPlatformGOPPolicyGuid} + SECTION PE32 = Vlv2MiscBinariesPkg/GOP/7.2.1011/RELEASE_VS2008x86/$(DXE_ARCHITECTURE)/IntelGopDriver.efi + SECTION UI = "IntelGopDriver" +} +!endif + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PnpDxe.inf + # + # SMM + # +INF MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf +INF MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PiSmmCpuDxeSmm.inf + +INF UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf +INF MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PiSmmCommunicationSmm.inf +INF $(PLATFORM_PACKAGE)/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PowerManagement2.inf +# INF Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/Dts/Smm/DigitalThermalSensor.inf + # + # ACPI + # +INF MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf +INF $(PLATFORM_PACKAGE)/BootScriptSaveDxe/BootScriptSaveDxe.inf +INF IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf +INF RuleOverride = ACPITABLE2 Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/PowerManagementAcpiTables.inf + +INF RuleOverride = ACPITABLE $(PLATFORM_RC_PACKAGE)/AcpiTablesPCAT/AcpiTables.inf + +INF $(PLATFORM_PACKAGE)/AcpiPlatform/AcpiPlatform.inf + + # + # PCI + # +INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/ISPDxe.inf + + +# +# ISA +# +INF $(PLATFORM_PACKAGE)/Wpce791/Wpce791.inf +INF IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf +INF IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf +!if $(SOURCE_DEBUG_ENABLE) != TRUE +INF IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf +!endif +INF IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf +INF IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf + +# +# SDIO +# +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MmcHost.inf +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MmcMediaDevice.inf +# +# IDE/SCSI/AHCI +# +INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + +INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + +INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf +!if $(SATA_ENABLE) == TRUE +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SataController.inf +# + +# +INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf +!if $(SCSI_ENABLE) == TRUE +INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf +INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf +!endif +# +!endif +# Console +# +INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf +INF Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf +INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf +INF IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf +INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf +INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf +INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + # + # USB + # +!if $(USB_ENABLE) == TRUE +INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf +INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf +INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf +INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf +INF MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf +INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf +INF MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf +!endif + + # + # ECP + # +INF EdkCompatibilityPkg/Compatibility/LegacyRegion2OnLegacyRegionThunk/LegacyRegion2OnLegacyRegionThunk.inf +INF EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.inf +INF EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.inf +INF EdkCompatibilityPkg/Compatibility/SmmAccess2OnSmmAccessThunk/SmmAccess2OnSmmAccessThunk.inf +INF EdkCompatibilityPkg/Compatibility/SmmControl2OnSmmControlThunk/SmmControl2OnSmmControlThunk.inf +INF EdkCompatibilityPkg/Compatibility/FvOnFv2Thunk/FvOnFv2Thunk.inf + # + # SMBIOS + # +INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf +INF $(PLATFORM_PACKAGE)/SmBiosMiscDxe/SmBiosMiscDxe.inf + +INF RuleOverride = BINARY $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmbiosMemory.inf + + # + # Legacy Modules + # +INF PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf + +# +# FAT file system +# +FILE DRIVER = 961578FE-B6B7-44c3-AF35-6BC705CD2B1F { + SECTION PE32 = FatBinPkg/EnhancedFatDxe/$(EDK_DXE_ARCHITECTURE)/Fat.efi + } +# +# UEFI Shell +# +FILE APPLICATION = PCD(gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile) { +# SECTION PE32 = EdkShellBinPkg/FullShell/$(EDK_DXE_ARCHITECTURE)/Shell_Full.efi + SECTION PE32 = EdkShellBinPkg/MinimumShell/$(EDK_DXE_ARCHITECTURE)/Shell.efi + } + + + +!if $(GOP_DRIVER_ENABLE) == TRUE +FILE FREEFORM = 878AC2CC-5343-46F2-B563-51F89DAF56BA { + SECTION RAW = Vlv2MiscBinariesPkg/GOP/7.2.1011/VBT/MNW2/Vbt.bin + SECTION UI = "IntelGopVbt" +} +!endif + +# +# Network Modules +# +!if $(NETWORK_ENABLE) == TRUE + FILE DRIVER = 22DE1691-D65D-456a-993E-A253DD1F308C { + SECTION PE32 = Vlv2MiscBinariesPkg/UNDI/RtkUndiDxe/$(DXE_ARCHITECTURE)/RtkUndiDxe.efi + SECTION UI = "UNDI" + } + INF MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf + INF MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf + INF MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf + INF MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf + INF MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf + INF MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf + INF MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf + INF MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf + INF MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf + !if $(NETWORK_IP6_ENABLE) == TRUE + INF NetworkPkg/Ip6Dxe/Ip6Dxe.inf + INF NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf + INF NetworkPkg/IpSecDxe/IpSecDxe.inf + INF NetworkPkg/Udp6Dxe/Udp6Dxe.inf + INF NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf + !endif + !if $(NETWORK_IP6_ENABLE) == TRUE + INF NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf + INF NetworkPkg/TcpDxe/TcpDxe.inf + !else + INF MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf + INF MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf + !endif + !if $(NETWORK_VLAN_ENABLE) == TRUE + INF MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf + !endif + !if $(NETWORK_ISCSI_ENABLE) == TRUE + !if $(NETWORK_IP6_ENABLE) == TRUE + INF NetworkPkg/IScsiDxe/IScsiDxe.inf + !else + INF MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf + !endif + !endif +!endif + +[FV.FVMAIN_COMPACT] +BlockSize = $(FLASH_BLOCK_SIZE) +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 { +!if $(LZMA_ENABLE) == TRUE +# LZMA Compress + SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + SECTION FV_IMAGE = FVMAIN + } +!else +!if $(DXE_COMPRESS_ENABLE) == TRUE +# Tiano Compress + SECTION GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE { + SECTION FV_IMAGE = FVMAIN + } +!else +# No Compress + SECTION COMPRESS PI_NONE { + SECTION FV_IMAGE = FVMAIN + } +!endif +!endif + } + +[FV.SETUP_DATA] +BlockSize = $(FLASH_BLOCK_SIZE) +#NumBlocks = 0x10 +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 + + +[FV.Update_Data] +BlockSize = $(FLASH_BLOCK_SIZE) +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 RAW = 88888888-8888-8888-8888-888888888888 { + FD = Vlv + } + +[FV.BiosUpdateCargo] +BlockSize = $(FLASH_BLOCK_SIZE) +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 + + + +[FV.BiosUpdate] +BlockSize = $(FLASH_BLOCK_SIZE) +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 + +[Capsule.Capsule_Boot] +# +# gEfiCapsuleGuid supported by platform +# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }} +# +CAPSULE_GUID = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0 +CAPSULE_FLAGS = PersistAcrossReset +CAPSULE_HEADER_SIZE = 0x20 + +FV = BiosUpdate + +[Capsule.Capsule_Reset] +# +# gEfiCapsuleGuid supported by platform +# { 0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }} +# +CAPSULE_GUID = 3B6686BD-0D76-4030-B70E-B5519E2FC5A0 +CAPSULE_FLAGS = PersistAcrossReset +CAPSULE_HEADER_SIZE = 0x20 + +FV = BiosUpdate + +################################################################################ +# +# 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 { + PE32 PE32 Align = 8 $(INF_OUTPUT)/$(MODULE_NAME).efi + RAW BIN Align = 16 |.com + } + +[Rule.Common.SEC.BINARY] + FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED { + PE32 PE32 Align = 8 |.efi + RAW BIN Align = 16 |.com + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + PE32 PE32 Align = Auto $(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 + PE32 PE32 Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.PEIM.BINARY] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional |.depex + PE32 PE32 Align = Auto |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.PEIM.BIOSID] + FILE PEIM = $(NAMED_GUID) { + RAW BIN BiosId.bin + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.USER_DEFINED.APINIT] + FILE RAW = $(NAMED_GUID) Fixed Align=4K { + RAW SEC_BIN |.com + } +#cjia 2011-07-21 +[Rule.Common.USER_DEFINED.LEGACY16] + FILE FREEFORM = $(NAMED_GUID) { + UI STRING="$(MODULE_NAME)" Optional + RAW BIN |.bin + } +#cjia + +[Rule.Common.USER_DEFINED.ASM16] + FILE FREEFORM = $(NAMED_GUID) { + UI STRING="$(MODULE_NAME)" Optional + RAW BIN |.com + } + +[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.UEFI_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_DRIVER.NATIVE_BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(WORKSPACE)/$(PLATFORM_PACKAGE)/IntelGopDepex/IntelGopDriver.depex + PE32 PE32 |.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_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_DRIVER.DRIVER_ACPITABLE] + 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) + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml + } + +[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_RUNTIME_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_SMM_DRIVER] + FILE SMM = $(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.BINARY] + FILE SMM = $(NAMED_GUID) { + SMM_DEPEX SMM_DEPEX |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_SMM_DRIVER.DRIVER_ACPITABLE] + FILE SMM = $(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) + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml + } + +[Rule.Common.SMM_CORE] + FILE SMM_CORE = $(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.SMM_CORE.BINARY] + FILE SMM_CORE = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(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.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] + FILE FREEFORM = $(NAMED_GUID) { + UI STRING="$(MODULE_NAME)" Optional + RAW BIN |.bin + } + +[Rule.Common.USER_DEFINED.ACPITABLE] + FILE FREEFORM = $(NAMED_GUID) { + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml + } + +[Rule.Common.USER_DEFINED.ACPITABLE2] + FILE FREEFORM = $(NAMED_GUID) { + RAW ASL Optional |.aml + } + +[Rule.Common.ACPITABLE] + FILE FREEFORM = $(NAMED_GUID) { + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml + } + diff --git a/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc b/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc new file mode 100644 index 0000000000..7963855cb7 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPkgGccX64.dsc @@ -0,0 +1,1492 @@ +#/** @file +# Platform description. +# +# Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = Vlv2TbltDevicePkg + PLATFORM_GUID = 465B0A0B-7AC1-443b-8F67-7B8DEC145F90 + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + + # + # Set platform specific package/folder name, same as passed from PREBUILD script. + # PLATFORM_PACKAGE would be the same as PLATFORM_NAME as well as package build folder + # DEFINE only takes effect at R9 DSC and FDF. + # + DEFINE PLATFORM_PACKAGE = Vlv2TbltDevicePkg + DEFINE PLATFORM_RC_PACKAGE = Vlv2DeviceRefCodePkg + DEFINE PLATFORM_BINARY_PACKAGE = Vlv2BinaryPkg + OUTPUT_DIRECTORY = Build/$(PLATFORM_PACKAGE) + SUPPORTED_ARCHITECTURES = IA32|X64 + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + + DEFINE CPU_ARCH =ValleyView2 + DEFINE PROJECT_SC_FAMILY =IntelPch + DEFINE PROJECT_SC_ROOT =../$(PLATFORM_RC_PACKAGE)/ValleyView2Soc/SouthCluster + DEFINE PROJECT_VLV_ROOT =../$(PLATFORM_RC_PACKAGE)/ValleyView2Soc/NorthCluster + + DEFINE RC_BINARY_RELEASE = TRUE + # + # Platform On/Off features are defined here + # + # + # Platform Support:: Set only one token except Crestview Hills + # + # 3.BayleyBay + # ENBDT_PF_ENABLE = TRUE + # + !include $(PLATFORM_PACKAGE)/AutoPlatformCFG.txt + !include $(PLATFORM_PACKAGE)/PlatformPkgConfig.dsc + +!if $(X64_CONFIG) == TRUE + DEFINE DXE_ARCHITECTURE = X64 + DEFINE EDK_DXE_ARCHITECTURE = X64 + DEFINE UNDI_DXE_ARCHITECTURE = 64 +!else + DEFINE DXE_ARCHITECTURE = IA32 + DEFINE EDK_DXE_ARCHITECTURE = Ia32 + DEFINE UNDI_DXE_ARCHITECTURE = 32 +!endif + + FLASH_DEFINITION = $(PLATFORM_PACKAGE)/PlatformPkgGcc.fdf +!if $(LFMA_ENABLE) == TRUE + FIX_LOAD_TOP_MEMORY_ADDRESS = 0xFFFFFFFFFFFFFFFF + DEFINE TOP_MEMORY_ADDRESS = 0xFFFFFFFFFFFFFFFF +!else + FIX_LOAD_TOP_MEMORY_ADDRESS = 0x0 + DEFINE TOP_MEMORY_ADDRESS = 0x0 +!endif + + DEFINE PLATFORM_PCIEXPRESS_BASE = 0E0000000 + + +################################################################################ +# +# 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.common] + # + # 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 + DxeSmmDriverEntryPoint|IntelFrameworkPkg/Library/DxeSmmDriverEntryPoint/DxeSmmDriverEntryPoint.inf + + # + # Basic + # + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf +!if $(SSE2_ENABLE) == TRUE + BaseMemoryLib|MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.inf +!else + BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf +!endif + 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 + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf +!if $(RC_BINARY_RELEASE) == TRUE + PchPlatformLib|Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLib.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 + 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 + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + GenericBdsLib|$(PLATFORM_PACKAGE)/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf + PlatformBdsLib|$(PLATFORM_PACKAGE)/Library/PlatformBdsLib/PlatformBdsLib.inf + NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf + DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf + FlashDeviceLib|$(PLATFORM_PACKAGE)/Library/FlashDeviceLib/FlashDeviceLib.inf + # + # Framework + # +!if $(S3_ENABLE) == TRUE + S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf +!else + S3BootScriptLib|MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf +!endif + S3IoLib|MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf + S3PciLib|MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf + + # + # Generic Modules + # +!if $(USB_ENABLE) == TRUE + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf +!endif +!if $(SCSI_ENABLE) == TRUE + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf +!endif +!if $(NETWORK_ENABLE) == TRUE + NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf + IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf + UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf + TcpIoLib|MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf + DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf +!endif +!if $(S3_ENABLE) == TRUE + S3Lib|IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf +!endif + + OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf +!if $(CAPSULE_ENABLE) == TRUE + CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf +!else + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf +!endif + LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + IoApicLib|PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + + # + # CPU + # + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf + LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf + CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf + + # + # ICH + # + SmbusLib|$(PLATFORM_PACKAGE)/Library/SmbusLib/SmbusLib.inf + SmmLib|$(PLATFORM_PACKAGE)/Library/PchSmmLib/PchSmmLib.inf + + # + # Platform + # + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf + ResetSystemLib|$(PLATFORM_PACKAGE)/Library/ResetSystemLib/ResetSystemLib.inf + + PlatformCmosLib|$(PLATFORM_PACKAGE)/Library/PlatformCmosLib/PlatformCmosLib.inf + + # + # Misc + # + MonoStatusCodeLib|$(PLATFORM_PACKAGE)/MonoStatusCode/MonoStatusCode.inf +!if $(TARGET) == RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf +!else + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf +!endif + + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf +!if $(TPM_ENABLED) == TRUE + TpmCommLib|SecurityPkg/Library/TpmCommLib/TpmCommLib.inf + Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf + DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf + PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf + SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf +!else + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf +!endif + + # + # CryptLib + # +!if $(TPM_ENABLED) == TRUE + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf +!endif + + BiosIdLib|$(PLATFORM_PACKAGE)/Library/BiosIdLib/BiosIdLib.inf + CpuIA32Lib|$(PLATFORM_PACKAGE)/Library/CpuIA32Lib/CpuIA32Lib.inf + + StallSmmLib|$(PLATFORM_PACKAGE)/Library/StallSmmLib/StallSmmLib.inf + + !if $(SECURE_BOOT_ENABLE) == TRUE + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf + !endif +!if $(RC_BINARY_RELEASE) == TRUE + I2cLib|Vlv2TbltDevicePkg/Library/I2CLib/I2CLibNull.inf +!endif + ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf + + TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf + TrEEPhysicalPresenceLib|SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.inf + Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf +!if $(MINNOW2_FSP_BUILD) == TRUE + FspApiLib|IntelFspWrapperPkg/Library/BaseFspApiLib/BaseFspApiLib.inf + FspPlatformInfoLib|IntelFspWrapperPkg/Library/BaseFspPlatformInfoLibSample/BaseFspPlatformInfoLibSample.inf + FspPlatformSecLib|Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/FspPlatformSecLibVlv2.inf + FspHobProcessLib|Vlv2TbltDevicePkg/FspSupport/Library/PeiFspHobProcessLibVlv2/FspHobProcessLibVlv2.inf +!endif + +[LibraryClasses.IA32.SEC] +!if $(PERFORMANCE_ENABLE) == TRUE + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf +!endif + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + +[LibraryClasses.IA32.PEIM, LibraryClasses.IA32.PEI_CORE, LibraryClasses.IA32.SEC] + # + # PEI phase common + # + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.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 + MultiPlatformLib|$(PLATFORM_PACKAGE)/Library/MultiPlatformLib/MultiPlatformLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf + + +!if $(PERFORMANCE_ENABLE) == TRUE + PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf + TimerLib|PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.inf +!endif + +!if $(TARGET) == RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf +!else + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf +!endif + + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + + !if $(MINNOW2_FSP_BUILD) == TRUE + PlatformFspLib|Vlv2TbltDevicePkg/Library/PlatformFspLib/PlatformFspLib.inf + !endif + + + +[LibraryClasses.X64] + # + # DXE phase common + # + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + + TcgPhysicalPresenceLib|SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.inf +!if $(TPM_ENABLED) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +!endif + + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf + EfiRegTableLib|$(PLATFORM_PACKAGE)/Library/EfiRegTableLib/EfiRegTableLib.inf + +!if $(SECURE_BOOT_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +!endif + + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf + +[LibraryClasses.X64.DXE_DRIVER] + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf +!if $(PERFORMANCE_ENABLE) == TRUE + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + TimerLib|PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + +[LibraryClasses.X64.DXE_CORE] + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf +!if $(PERFORMANCE_ENABLE) == TRUE + PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf + TimerLib|PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + +[LibraryClasses.X64.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 + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf + !if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + !endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf +!endif + CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf + +[LibraryClasses.X64.SMM_CORE] + MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf + SmmServicesTableLib|MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf + SmmCorePlatformHookLib|MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf + +!if $(TPM_ENABLED) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf +!endif + + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf +!endif + +[LibraryClasses.X64.DXE_RUNTIME_DRIVER] + ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf +!if $(SECURE_BOOT_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf +!endif +!if $(TPM_ENABLED) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + +[LibraryClasses.common.UEFI_DRIVER] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + +[LibraryClasses.X64.UEFI_APPLICATION] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + + +################################################################################ +# +# Library Section - list of all EDK/Framework libraries +# +################################################################################ +[Libraries.common] + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseLib/BaseLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseMemoryLib/BaseMemoryLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePrintLib/BasePrintLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseDebugLibNull/BaseDebugLibNull.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePciCf8Lib/BasePciCf8Lib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePciExpressLib/BasePciExpressLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePciLibCf8/BasePciLibCf8.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePeCoffLib/BasePeCoffLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/SmmRuntimeDxeReportStatusCodeLib/SmmRuntimeDxeReportStatusCodeLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiHobLib/PeiHobLib.inf + EdkCompatibilityPkg/Foundation/Ppi/EdkPpiLib.inf + EdkCompatibilityPkg/Foundation/Library/Pei/PeiLib/PeiLib.inf + EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf + EdkCompatibilityPkg/Foundation/Guid/EdkGuidLib.inf + EdkCompatibilityPkg/Foundation/Efi/Protocol/EfiProtocolLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/EfiDriverLib/EfiDriverLib.inf + EdkCompatibilityPkg/Foundation/Protocol/EdkProtocolLib.inf + EdkCompatibilityPkg/Foundation/Framework/Protocol/EdkFrameworkProtocolLib.inf +[Libraries.IA32] + EdkCompatibilityPkg/Foundation/Efi/Guid/EfiGuidLib.inf + EdkCompatibilityPkg/Foundation/Framework/Guid/EdkFrameworkGuidLib.inf + EdkCompatibilityPkg/Foundation/Library/EfiCommonLib/EfiCommonLib.inf + EdkCompatibilityPkg/Foundation/Cpu/Pentium/CpuIA32Lib/CpuIA32Lib.inf + EdkCompatibilityPkg/Foundation/Library/CompilerStub/CompilerStubLib.inf + EdkCompatibilityPkg/Foundation/Framework/Ppi/EdkFrameworkPpiLib.inf + EdkCompatibilityPkg/Foundation/Library/Pei/Hob/PeiHobLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointerLibMm7.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiServicesLib/PeiServicesLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf + EdkCompatibilityPkg/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.inf + + $(PLATFORM_PACKAGE)/Library/MultiPlatformLib/MultiPlatformLib.inf +[Libraries.X64] + + EdkCompatibilityPkg/Foundation/Efi/Guid/EfiGuidLib.inf + EdkCompatibilityPkg/Foundation/Framework/Guid/EdkFrameworkGuidLib.inf + EdkCompatibilityPkg/Foundation/Library/EfiCommonLib/EfiCommonLib.inf + EdkCompatibilityPkg/Foundation/Cpu/Pentium/CpuIA32Lib/CpuIA32Lib.inf + EdkCompatibilityPkg/Foundation/Library/CompilerStub/CompilerStubLib.inf + EdkCompatibilityPkg/Foundation/Framework/Ppi/EdkFrameworkPpiLib.inf + EdkCompatibilityPkg/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/Hob/HobLib.inf + EdkCompatibilityPkg/Foundation/Library/RuntimeDxe/EfiRuntimeLib/EfiRuntimeLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/EfiIfrSupportLib/EfiIfrSupportLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/Print/PrintLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/EfiScriptLib/EfiScriptLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/PrintLite/PrintLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/GraphicsLite/Graphics.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiLib/UefiLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/DxeHobLib/DxeHobLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/HiiLib/HiiLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiDevicePathLib/UefiDevicePathLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiDriverModelLib/UefiDriverModelLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/DxeServicesTableLib/DxeServicesTableLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/EdkDxeRuntimeDriverLib/EdkDxeRuntimeDriverLib.inf + + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ +[PcdsFeatureFlag.common] +!if $(MINI_BIOS_ENABLE) == FALSE + gPlatformModuleTokenSpaceGuid.PcdBdsDispatchAdditionalOprom|TRUE +!else + gPlatformModuleTokenSpaceGuid.PcdBdsDispatchAdditionalOprom|FALSE +!endif +# +# If PcdDxeIplSwitchToLongMode is TRUE, DxeIpl will load a 64-bit DxeCore and switch to long mode to hand over to DxeCore. +# + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE + + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserGrayOutTextStatement|TRUE + +!if $(CAPSULE_RESET_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|TRUE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|FALSE +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport|TRUE + gEfiCpuTokenSpaceGuid.PcdCpuSmmEnableBspElection|FALSE +!if $(DATAHUB_STATUS_CODE_ENABLE) == TRUE + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub|TRUE +!else + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub|FALSE +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst|FALSE +!if $(TARGET) == RELEASE + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE +!if $(ISA_SERIAL_STATUS_CODE_ENABLE) == TRUE + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseIsaSerial|TRUE +!else + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseIsaSerial|FALSE +!endif +!if $(USB_SERIAL_STATUS_CODE_ENABLE) == TRUE + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseUsbSerial|TRUE +!else + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseUsbSerial|FALSE +!endif +!if $(RAM_SERIAL_STATUS_CODE_ENABLE) == TRUE + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseRam|TRUE +!else + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseRam|FALSE +!endif + + + ## This PCD specifies whether PS2 keyboard does a extended verification during start. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification|FALSE + + ## This PCD specifies whether PS2 mouse does a extended verification during start. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2MouseExtendedVerification|FALSE + +!if $(VARIABLE_INFO_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics|TRUE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics|FALSE +!endif + + gEfiCpuTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp|TRUE + +[PcdsFixedAtBuild.common] +!if $(MINNOW2_FSP_BUILD) == TRUE +# $(FLASH_REGION_VLVMICROCODE_BASE) + gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchAddress|0xFFE00000 +# $(FLASH_REGION_VLVMICROCODE_SIZE) + gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize|0x00030000 + gFspWrapperTokenSpaceGuid.PcdFlashMicroCodeOffset|0x60 +# $(FLASH_AREA_BASE_ADDRESS) + gFspWrapperTokenSpaceGuid.PcdFlashCodeCacheAddress|0xFF800000 +# $(FLASH_AREA_SIZE) + gFspWrapperTokenSpaceGuid.PcdFlashCodeCacheSize|0x00800000 +# $(FLASH_REGION_FSPBIN_BASE) + gFspWrapperTokenSpaceGuid.PcdFlashFvFspBase|0xFFDB0000 +!endif + +!if $(PERFORMANCE_ENABLE) == TRUE +!if $(MINNOW2_FSP_BUILD) == TRUE + # in FSP, when this got used, the memory already is up + gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0x00080000 +!else + gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0xFEF80000 +!endif + gEfiCpuTokenSpaceGuid.PcdTemporaryRamSize|0x00010000 + +!else + !if $(MINNOW2_FSP_BUILD) == TRUE + gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0x00080000 + !else + gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0xFEF80000 + !endif + gEfiCpuTokenSpaceGuid.PcdTemporaryRamSize|0x00010000 + gEfiCpuTokenSpaceGuid.PcdPeiTemporaryRamStackSize|0x3C00 +!endif + + +!if $(SECURE_BOOT_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x22000 +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x4000 +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize|0x00000800 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x400 + gEfiCpuTokenSpaceGuid.PcdCpuIEDRamSize|0x400000 + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize|0x10000 + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeimPerFv|50 + gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPpiSupported|128 + gEfiCpuTokenSpaceGuid.PcdCpuSmmApSyncTimeout|1000 +!if $(S4_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|TRUE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE +!endif +!if $(TARGET) == RELEASE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x3 +!else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 +!endif +!if $(PERFORMANCE_ENABLE) == TRUE + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0x1 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|60 +!endif + + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize|0x10000 + gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable|$(TOP_MEMORY_ADDRESS) + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserSubtitleTextColor|0x0 + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextColor|0x01 + gEfiCpuTokenSpaceGuid.PcdCpuIEDEnabled|TRUE + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable|TRUE + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable|TRUE + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl|FALSE +!endif + +[PcdsFixedAtBuild.IA32.PEIM, PcdsFixedAtBuild.IA32.PEI_CORE, PcdsFixedAtBuild.IA32.SEC] +!if $(TARGET) == RELEASE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x3 +!else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2E + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 +!endif + +[PcdsPatchableInModule.common] + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x803805c6 + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0x$(PLATFORM_PCIEXPRESS_BASE) + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion|FALSE + + ## This PCD specifies whether to use the optimized timing for best PS2 detection performance. + # Note this PCD could be set to TRUE for best boot performance and set to FALSE for best device compatibility. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFastPS2Detection|TRUE + +[PcdsDynamicHii.common.DEFAULT] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|5 # Variable: L"Timeout" + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|L"HwErrRecSupport"|gEfiGlobalVariableGuid|0x0|1 # Variable: L"HwErrRecSupport" + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState|L"BootState"|gEfiBootStateGuid|0x0|TRUE + +[PcdsDynamicDefault.common.DEFAULT] + gEfiMdeModulePkgTokenSpaceGuid.PcdS3BootScriptTablePrivateDataPtr|0x0 + !if $(TPM_ENABLED) == TRUE + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x7b, 0x3a, 0xcd, 0x72, 0xA5, 0xFE, 0x5e, 0x4f, 0x91, 0x65, 0x4d, 0xd1, 0x21, 0x87, 0xbb, 0x13} + !endif + + ## This PCD defines the video horizontal resolution. + # This PCD could be set to 0 then video resolution could be at highest resolution. + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|0 + ## This PCD defines the video vertical resolution. + # This PCD could be set to 0 then video resolution could be at highest resolution. + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|0 + + ## This PCD defines the Console output column and the default value is 25 according to UEFI spec. + # This PCD could be set to 0 then console output could be at max column and max row. + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|31 + ## This PCD defines the Console output row and the default value is 80 according to UEFI spec. + # This PCD could be set to 0 then console output could be at max column and max row. + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|100 + + ## The PCD is used to specify the video horizontal resolution of text setup. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|800 + ## The PCD is used to specify the video vertical resolution of text setup. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|600 + ## The PCD is used to specify the console output column of text setup. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupConOutColumn|100 + ## The PCD is used to specify the console output column of text setup. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupConOutRow|31 + +!if $(TPM_ENABLED) == TRUE + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInitializationPolicy|1 + gEfiSecurityPkgTokenSpaceGuid.PcdTpmScrtmPolicy|1 +!endif + +[PcdsDynamicExDefault.common.DEFAULT] + gEfiVLVTokenSpaceGuid.PcdTCSmbaIoBaseAddress|0x1040 + gEfiVLVTokenSpaceGuid.PcdEmmcManufacturerId|0 + gEfiVLVTokenSpaceGuid.PcdProductSerialNumber|0 + gEfiVLVTokenSpaceGuid.PcdMeasuredBootEnable|TRUE + gEfiVLVTokenSpaceGuid.PcdFTPMErrorOccur|FALSE + gEfiVLVTokenSpaceGuid.PcdFTPMErrorSkip|FALSE + gEfiVLVTokenSpaceGuid.PcdFTPMCommand|0 + gEfiVLVTokenSpaceGuid.PcdFTPMResponse|0 + gEfiVLVTokenSpaceGuid.PcdFTPMNotRespond|FALSE + gEfiVLVTokenSpaceGuid.PcdFTPMStatus|0 + +[Components.IA32] + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf + + !if $(MINNOW2_FSP_BUILD) == TRUE + IntelFspWrapperPkg/FspWrapperSecCore/FspWrapperSecCore.inf { + !if $(TARGET) == DEBUG + + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + } + Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.inf + IntelFspWrapperPkg/FspInitPei/FspInitPei.inf { + !if $(TARGET) == DEBUG + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + } + !endif + + MdeModulePkg/Core/Pei/PeiMain.inf { +!if $(TARGET) == DEBUG + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2E +!endif + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + !if $(TARGET) == DEBUG + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf + !endif + } + + $(PLATFORM_PACKAGE)/MonoStatusCode/MonoStatusCode.inf { +!if $(TARGET) == DEBUG + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2E +!endif + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MemoryInit.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + } + +!if $(RC_BINARY_RELEASE) == TRUE + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SeCUma.inf +!endif + +!if $(RC_BINARY_RELEASE) == TRUE + $(PLATFORM_PACKAGE)/PlatformPei/PlatformPei.inf { + + *_*_IA32_CC_FLAGS = -DRC_BINARY_RELEASE + !if $(TARGET) == DEBUG + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2E + !endif + } +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + SourceLevelDebugPkg/DebugAgentPei/DebugAgentPei.inf{ + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf + PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf + SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf + } +!endif + + +!if $(TPM_ENABLED) == TRUE + SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf + SecurityPkg/Tcg/TcgPei/TcgPei.inf { + + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf +} +!endif + + $(PLATFORM_PACKAGE)/PlatformInitPei/PlatformInitPei.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x803805c6 + +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf +!endif + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + } + $(PLATFORM_PACKAGE)/FvInfoPei/FvInfoPei.inf + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/VlvInitPeim.inf +!if $(PCIESC_ENABLE) == TRUE + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchEarlyInitPeim.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + } +!endif + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchInitPeim.inf + + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchSmbusArpDisabled.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchSpiPeim.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PeiSmmAccess.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PeiSmmControl.inf + MdeModulePkg/Universal/PCD/Pei/Pcd.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/CpuPeim.inf + UefiCpuPkg/CpuIoPei/CpuIoPei.inf + UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf + EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf +!if $(CAPSULE_ENABLE) == TRUE + MdeModulePkg/Universal/CapsulePei/CapsulePei.inf +!endif + MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf { + +!if $(LZMA_ENABLE) == TRUE + NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf +!endif + } + +!if $(SECURE_BOOT_ENABLE) == TRUE + SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf +!else + MdeModulePkg/Universal/Variable/Pei/VariablePei.inf +!endif + MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf + +!if $(TPM_ENABLED) == TRUE + SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf { + + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + } +!endif +!if $(ACPI50_ENABLE) == TRUE + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf{ + + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf + } + +!endif +!if $(PERFORMANCE_ENABLE) == TRUE + MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf +!endif +[Components.X64] + !if $(MINNOW2_FSP_BUILD) == TRUE + IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.inf { + !if $(TARGET) == DEBUG + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + } + + !endif + # + # EDK II Related Platform codes + # + MdeModulePkg/Core/Dxe/DxeMain.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + +!if $(DXE_CRC32_SECTION_ENABLE) == TRUE + NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf +!endif +!if $(LZMA_ENABLE) == TRUE + NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf +!endif +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf +!endif + } + IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x27 + + !if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + !endif + + ICC:*_*_*_CC_FLAGS = -D MDEPKG_NDEBUG + GCC:*_*_*_CC_FLAGS = -D MDEPKG_NDEBUG + } + MdeModulePkg/Universal/PCD/Dxe/Pcd.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf + UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf +!if $(PERFORMANCE_ENABLE) == TRUE + MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf +!endif + MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf { + +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf +!endif + } + +!if $(CAPSULE_ENABLE) == TRUE + MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf { + + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + } +!endif + + MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf{ + +!if $(SECURE_BOOT_ENABLE) == TRUE + NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf +!endif +!if $(USER_IDENTIFICATION_ENABLE) + NULL|SecurityPkg/Library/DxeDeferImageLoadLib/DxeDeferImageLoadLib.inf +!endif +!if $(TPM_ENABLED) == TRUE + NULL|SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf +!endif + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MpCpu.inf + $(PLATFORM_PACKAGE)/Metronome/Metronome.inf + + IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf{ + + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + PlatformBdsLib|$(PLATFORM_PACKAGE)/Library/PlatformBdsLib/PlatformBdsLib.inf + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf + } + + $(PLATFORM_PACKAGE)/UiApp/UiApp.inf + + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf +!if $(SECURE_BOOT_ENABLE) == TRUE + SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf + SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf{ + + PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf + } + $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbSmm.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiSmm.inf + SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf { + + PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf + + # + # Specify GUID gEfiIfrBootMaintenanceGuid, to install Secure Boot Configuration menu + # into Boot Maintenance Manager menu + # + *_*_*_VFR_FLAGS = -g b2dedc91-d59f-48d2-898a-12490c74a4e0 + } + !else + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf + $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbSmm.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiSmm.inf +!endif + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf { + + FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + } + + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + + $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbRuntimeDxe.inf + + $(PLATFORM_PACKAGE)/PlatformSetupDxe/PlatformSetupDxe.inf + +!if $(DATAHUB_ENABLE) == TRUE + IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|0 + } +!endif + IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf + MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchS3SupportDxe.inf + !if $(USE_HPET_TIMER) == TRUE + PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf + !else + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmartTimer.inf + !endif + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmmControl.inf + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSmbusDxe.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/IntelPchLegacyInterrupt.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchReset.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchInitDxe.inf{ + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSmiDispatcher.inf + +!if $(PCIESC_ENABLE) == TRUE + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchPcieSmm.inf +!endif + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiRuntime.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchPolicyInitDxe.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchBiosWriteProtect.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmmAccess.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PciHostBridge.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/VlvInitDxe.inf + + IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf + + Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInitDxe.inf{ + +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf +!endif + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/Dptf.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PnpDxe.inf + +!if $(TPM_ENABLED) == TRUE + SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf { + + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + } + + SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf { + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + + # + # specify GUID gEfiIfrNotInTPVPageGuid, this page will not + # be showed in TPV page. + # + *_*_*_VFR_FLAGS = -g e58809f8-fbc1-48e2-883a-a30fdc4b441e + } + + SecurityPkg/Tcg/TcgDxe/TcgDxe.inf { + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + SecurityPkg/Tcg/TcgSmm/TcgSmm.inf +!endif + # + # EDK II Related Platform codes + # + $(PLATFORM_PACKAGE)/PlatformSmm/PlatformSmm.inf{ + + !if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + !endif + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + $(PLATFORM_PACKAGE)/PlatformInfoDxe/PlatformInfoDxe.inf + $(PLATFORM_PACKAGE)/PlatformCpuInfoDxe/PlatformCpuInfoDxe.inf + $(PLATFORM_PACKAGE)/PlatformDxe/PlatformDxe.inf + + $(PLATFORM_PACKAGE)/PciPlatform/PciPlatform.inf + $(PLATFORM_PACKAGE)/SaveMemoryConfig/SaveMemoryConfig.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PlatformCpuPolicy.inf + $(PLATFORM_PACKAGE)/PpmPolicy/PpmPolicy.inf + $(PLATFORM_PACKAGE)/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.inf +!if $(GOP_DRIVER_ENABLE) == TRUE + $(PLATFORM_PACKAGE)/PlatformGopPolicy/PlatformGopPolicy.inf + +!endif + + + # + # SMM + # + MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf + MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf{ + !if $(TARGET) != RELEASE + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf + !endif + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PiSmmCpuDxeSmm.inf + UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf + MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PiSmmCommunicationSmm.inf + $(PLATFORM_PACKAGE)/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PowerManagement2.inf + + # + # ACPI + # + MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x27 + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + + $(PLATFORM_PACKAGE)/BootScriptSaveDxe/BootScriptSaveDxe.inf + IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf + Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/PowerManagementAcpiTables.inf + + $(PLATFORM_RC_PACKAGE)/AcpiTablesPCAT/AcpiTables.inf + + $(PLATFORM_PACKAGE)/AcpiPlatform/AcpiPlatform.inf + + # + # PCI + # + MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/ISPDxe.inf + + +# +# ISA +# + $(PLATFORM_PACKAGE)/Wpce791/Wpce791.inf + IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf + IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf + IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf + IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf + IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf +# +# SDIO +# + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MmcHost.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MmcMediaDevice.inf +!if $(ACPI50_ENABLE) == TRUE + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf { + + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf + } + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf { + + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf + } +!endif + +# +# IDE/SCSI/AHCI +# + MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf + IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf +!if $(SATA_ENABLE) == TRUE + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SataController.inf +!endif + MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +!if $(SCSI_ENABLE) == TRUE + MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf +!endif +# +# Console +# + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf + MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + + # + # USB + # +!if $(USB_ENABLE) == TRUE + MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf + MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf + MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf + MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf + MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + +!endif + + # + # ECP + # + EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/FrameworkHiiOnUefiHiiThunk.inf + EdkCompatibilityPkg/Compatibility/LegacyRegion2OnLegacyRegionThunk/LegacyRegion2OnLegacyRegionThunk.inf + EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.inf + EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.inf + EdkCompatibilityPkg/Compatibility/SmmAccess2OnSmmAccessThunk/SmmAccess2OnSmmAccessThunk.inf + EdkCompatibilityPkg/Compatibility/SmmControl2OnSmmControlThunk/SmmControl2OnSmmControlThunk.inf + EdkCompatibilityPkg/Compatibility/FrameworkSmmStatusCodeOnPiSmmStatusCodeThunk/FrameworkSmmStatusCodeOnPiSmmStatusCodeThunk.inf + EdkCompatibilityPkg/Compatibility/FvOnFv2Thunk/FvOnFv2Thunk.inf + # + # SMBIOS + # + MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + $(PLATFORM_PACKAGE)/SmBiosMiscDxe/SmBiosMiscDxe.inf + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmbiosMemory.inf + # + # CPU/FW Microde + # + Vlv2MiscBinariesPkg/Microcode/MicrocodeUpdates.inf { + + *_*_*_GENFW_FLAGS = -a 0x800 -p 0xFF + } + + + PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf + + +!if $(NETWORK_ENABLE) == TRUE + !if $(NETWORK_ISCSI_ENABLE) == TRUE + !if $(NETWORK_IP6_ENABLE) == TRUE + NetworkPkg/IScsiDxe/IScsiDxe.inf + !else + MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf + !endif + !endif + !if $(NETWORK_VLAN_ENABLE) == TRUE + MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf + !endif + !if $(CSM_ENABLE) == TRUE + IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf + !endif +!endif + +!if $(NETWORK_ENABLE) == TRUE + # + # UEFI network modules + # + MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf + MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf + + MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf + MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf + MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf + MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf + MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf + MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf + MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000 + } + MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf + !if $(NETWORK_IP6_ENABLE) == TRUE + NetworkPkg/Ip6Dxe/Ip6Dxe.inf + NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf + NetworkPkg/IpSecDxe/IpSecDxe.inf + NetworkPkg/TcpDxe/TcpDxe.inf + NetworkPkg/Udp6Dxe/Udp6Dxe.inf + NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf + !endif + !if $(NETWORK_IP6_ENABLE) == TRUE + NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf + !else + MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf + !endif +!endif + + Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf + +[BuildOptions] +# +# Define Build Options both for EDK and EDKII drivers. +# + +# +# Define token for different Platform +# +!if $(MINNOW2_FSP_BUILD) == TRUE + DEFINE MINNOW2_FSP_OPTION = -DMINNOW2_FSP_BUILD +!else + DEFINE MINNOW2_FSP_OPTION = +!endif + +!if $(ENBDT_PF_BUILD) == TRUE + DEFINE ENBDT_PF_ENABLE = -DENBDT_PF_ENABLE=1 +!else + DEFINE ENBDT_PF_ENABLE = -DENBDT_PF_ENABLE=0 +!endif + + +!if $(CLKGEN_CONFIG_EXTRA_ENABLE) == TRUE + DEFINE CLKGEN_CONFIG_EXTRA_BUILD_OPTION = -DCLKGEN_CONFIG_EXTRA=1 +!else + DEFINE CLKGEN_CONFIG_EXTRA_BUILD_OPTION = +!endif + + + +!if $(PCIESC_ENABLE) == TRUE + DEFINE PCIESC_SUPPORT_BUILD_OPTION = -DPCIESC_SUPPORT=1 +!else + DEFINE PCIESC_SUPPORT_BUILD_OPTION = +!endif +!if $(SATA_ENABLE) == TRUE + DEFINE SATA_SUPPORT_BUILD_OPTION = -DSATA_SUPPORT=1 +!else + DEFINE SATA_SUPPORT_BUILD_OPTION = +!endif +!if $(ENBDT_S3_SUPPORT) == TRUE + DEFINE ENBDT_S3_SUPPORT_OPTIONS = -DNOCS_S3_SUPPORT +!else + DEFINE ENBDT_S3_SUPPORT_OPTIONS = +!endif + +!if $(X64_CONFIG) == TRUE + DEFINE X64_BUILD_ENABLE = -DX64_BUILD_ENABLE=1 +!else + DEFINE X64_BUILD_ENABLE = +!endif + +!if $(TPM_ENABLED) == TRUE + DEFINE DSC_TPM_BUILD_OPTIONS = -DTPM_ENABLED +!else + DEFINE DSC_TPM_BUILD_OPTIONS = +!endif + + + DEFINE EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS = $(MINNOW2_FSP_OPTION) $(MINNOW2_BUILD_OPTION) $(ENBDT_PF_ENABLE) $(EXTERNAL_VGA_BUILD_OPTION) $(PCIE_ENUM_WA_BUILD_OPTION) $(X0_WA_ENABLE_BUILD_OPTION) $(A0_WA_ENABLE_BUILD_OPTION) $(MICROCODE_FREE_BUILD_OPTIONS) $(SIMICS_BUILD_OPTIONS) $(HYBRID_BUILD_OPTIONS) $(COMPACT_BUILD_OPTIONS) $(VP_BUILD_OPTIONS) $(SYSCTL_ID_BUILD_OPTION) $(CLKGEN_CONFIG_EXTRA_BUILD_OPTION) $(SYSCTL_X0_CONVERT_BOARD_OPTION) $(ENBDT_S3_SUPPORT_OPTIONS) $(SATA_SUPPORT_BUILD_OPTION) $(PCIESC_SUPPORT_BUILD_OPTION) $(DSC_FTPM_ERROR_WR_BUILD_OPTIONS) $(DSC_TPM_BUILD_OPTIONS) $(DSC_BYTI_SECURE_BOOT_BUILD_OPTIONS) +!if $(PERFORMANCE_ENABLE) == TRUE + DEFINE PDB_BUILD_OPTION = /Zi +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + MSFT:*_*_X64_GENFW_FLAGS = --keepexceptiontable + GCC:*_*_X64_GENFW_FLAGS = --keepexceptiontable + INTEL:*_*_X64_GENFW_FLAGS = --keepexceptiontable +!if $(TARGET) == DEBUG + DEFINE SOURCE_LEVEL_DEBUG_BUILD_OPTIONS = /Od /Oy- +!endif +!else + DEFINE SOURCE_LEVEL_DEBUG_BUILD_OPTIONS = + +!endif + +[BuildOptions.Common.EDK] + +# +# Define token for different Platform +# +!if $(ENBDT_PF_BUILD) == TRUE + DEFINE ENBDT_PF_ENABLE = -DENBDT_PF_ENABLE=1 +!else + DEFINE ENBDT_PF_ENABLE = -DENBDT_PF_ENABLE=0 +!endif + +!if $(PERFORMANCE_ENABLE) == TRUE + RELEASE_*_*_DLINK_FLAGS = -DEBUG +!endif + +!if $(S3_ENABLE) == TRUE + DEFINE DSC_S3_BUILD_OPTIONS = -DEFI_S3_RESUME +!else + DEFINE DSC_S3_BUILD_OPTIONS = +!endif + +!if $(ENBDT_S3_SUPPORT) == TRUE + DEFINE ENBDT_S3_SUPPORT_OPTIONS = -DNOCS_S3_SUPPORT +!else + DEFINE ENBDT_S3_SUPPORT_OPTIONS = +!endif + +!if $(X64_CONFIG) == TRUE + DEFINE X64_BUILD_ENABLE = -DX64_BUILD_ENABLE=1 +!else + DEFINE X64_BUILD_ENABLE = +!endif + + + DEFINE EDK_GLUE_LIB_DEBUG = + DEFINE DEBUG_BUILD_OPTIONS = -D EFI_DEBUG -D DEBUG_MODE=1 /GL- $(EDK_GLUE_LIB_DEBUG) -DEDKII_GLUE_DebugPrintErrorLevel=(EFI_D_ERROR) + DEFINE EDK_DSC_FEATURE_BUILD_OPTIONS = $(DSC_S3_BUILD_OPTIONS) $(DSC_ACPI_BUILD_OPTIONS) $(DSC_SEC_BUILD_OPTIONS) $(DSC_FTPM_BUILD_OPTIONS) $(DSC_FTPM_ERROR_WR_BUILD_OPTIONS) $(DSC_TPM_BUILD_OPTIONS) $(SOFTSDV_BUILD_OPTIONS) $(SIMICS_BUILD_OPTIONS) $(HYBRID_BUILD_OPTIONS) $(COMPACT_BUILD_OPTIONS) $(VP_BUILD_OPTIONS) $(QT_BUILD_OPTIONS) $(DSC_BYTI_SECURE_BOOT_BUILD_OPTIONS) -D$(PROJECT_SC_CHIPSET) + + DEFINE EDK_DSC_OTHER_BUILD_OPTIONS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) $(SV_BUILD_OPTIONS) $(INTEL_FASTBOOT_BUILD_OPTION) + DEFINE EDK_DSC_GLOBAL_BUILD_OPTIONS = $(ENBDT_PF_ENABLE) $(EDK_DSC_FEATURE_BUILD_OPTIONS) $(EDK_DSC_OTHER_BUILD_OPTIONS) -D EFI_SPECIFICATION_VERSION=0x00020000 -D PI_SPECIFICATION_VERSION=0x00000009 -D TIANO_RELEASE_VERSION=0x00080006 -D SUPPORT_DEPRECATED_PCI_CFG_PPI -D CSM_SMMENTRY_PORT8DATA8 -D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) -D MAX_VARIABLE_SIZE=0x2000 -D EFI_FIRMWARE_VENDOR="L/"INTEL/"" -D EFI_BUILD_VERSION="L/"EDKII/"" -DEFI_PEI_REPORT_STATUS_CODE_ON $(ENBDT_S3_SUPPORT_OPTIONS) + + *_*_IA32_ASM_FLAGS = -DEFI32 -D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h -DNOCS_S3_SUPPORT + DEBUG_*_IA32_CC_FLAGS = -D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_IA32_CC_FLAGS = -D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_IA32_VFRPP_FLAGS = -D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_IA32_VFRPP_FLAGS = -D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_IA32_APP_FLAGS = -D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_IA32_APP_FLAGS = -D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_IA32_PP_FLAGS = -D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_IA32_PP_FLAGS = -D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + *_*_IA32_ASLPP_FLAGS = -D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) + *_*_IA32_ASLCC_FLAGS = -D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) + *_*_IA32_ASM16_FLAGS = -D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h + + *_*_X64_ASM_FLAGS = -DEFIX64 -D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h -DNOCS_S3_SUPPORT + DEBUG_*_X64_CC_FLAGS = -D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_X64_CC_FLAGS = -D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_X64_VFRPP_FLAGS = -D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_X64_VFRPP_FLAGS = -D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_X64_APP_FLAGS = -D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_X64_APP_FLAGS = -D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_X64_PP_FLAGS = -D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_X64_PP_FLAGS = -D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + *_*_X64_ASLPP_FLAGS = -D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) + *_*_X64_ASLCC_FLAGS = -D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) + *_*_X64_ASM16_FLAGS = -D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h + # *_*_*_BUILD_FLAGS = -s + *_*_*_VFR_FLAGS = -c + *_*_*_BUILD_FLAGS = -c + +[BuildOptions.Common.EDKII] + *_*_IA32_ASM_FLAGS = $(VP_BUILD_OPTIONS) -D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h -DNOCS_S3_SUPPORT + + *_*_IA32_CC_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_IA32_VFRPP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_IA32_APP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_IA32_PP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_IA32_ASLPP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + + *_*_X64_CC_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) $(SOURCE_LEVEL_DEBUG_BUILD_OPTIONS) + *_*_X64_VFRPP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_X64_APP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_X64_PP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_X64_ASLPP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + + +[Components.X64] + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SysFwUpdateCapsuleDxe.inf + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/I2cBus.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + } + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/I2cHost.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/I2cPortA0Pio.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x00000043 + } + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/I2cMmioDeviceDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x00000043 + } diff --git a/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc b/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc new file mode 100644 index 0000000000..113d282750 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc @@ -0,0 +1,1480 @@ +#/** @file +# Platform description. +# +# Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = Vlv2TbltDevicePkg + PLATFORM_GUID = 465B0A0B-7AC1-443b-8F67-7B8DEC145F90 + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + + # + # Set platform specific package/folder name, same as passed from PREBUILD script. + # PLATFORM_PACKAGE would be the same as PLATFORM_NAME as well as package build folder + # DEFINE only takes effect at R9 DSC and FDF. + # + DEFINE PLATFORM_PACKAGE = Vlv2TbltDevicePkg + DEFINE PLATFORM_RC_PACKAGE = Vlv2DeviceRefCodePkg + DEFINE PLATFORM_BINARY_PACKAGE = Vlv2BinaryPkg + OUTPUT_DIRECTORY = Build/$(PLATFORM_PACKAGE) + SUPPORTED_ARCHITECTURES = IA32 + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + + DEFINE CPU_ARCH =ValleyView2 + DEFINE PROJECT_SC_FAMILY =IntelPch + DEFINE PROJECT_SC_ROOT =../$(PLATFORM_RC_PACKAGE)/ValleyView2Soc/SouthCluster + DEFINE PROJECT_VLV_ROOT =../$(PLATFORM_RC_PACKAGE)/ValleyView2Soc/NorthCluster + + DEFINE RC_BINARY_RELEASE = TRUE + # + # Platform On/Off features are defined here + # + # + # Platform Support:: Set only one token except Crestview Hills + # + # 3.BayleyBay + # ENBDT_PF_ENABLE = TRUE + # + !include $(PLATFORM_PACKAGE)/AutoPlatformCFG.txt + !include $(PLATFORM_PACKAGE)/PlatformPkgConfig.dsc + +!if $(X64_CONFIG) == TRUE + DEFINE DXE_ARCHITECTURE = X64 + DEFINE EDK_DXE_ARCHITECTURE = X64 + DEFINE UNDI_DXE_ARCHITECTURE = 64 +!else + DEFINE DXE_ARCHITECTURE = IA32 + DEFINE EDK_DXE_ARCHITECTURE = Ia32 + DEFINE UNDI_DXE_ARCHITECTURE = 32 +!endif + + FLASH_DEFINITION = $(PLATFORM_PACKAGE)/PlatformPkg.fdf +!if $(LFMA_ENABLE) == TRUE + FIX_LOAD_TOP_MEMORY_ADDRESS = 0xFFFFFFFFFFFFFFFF + DEFINE TOP_MEMORY_ADDRESS = 0xFFFFFFFFFFFFFFFF +!else + FIX_LOAD_TOP_MEMORY_ADDRESS = 0x0 + DEFINE TOP_MEMORY_ADDRESS = 0x0 +!endif + + DEFINE PLATFORM_PCIEXPRESS_BASE = 0E0000000 + + +################################################################################ +# +# 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.common] + # + # 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 + DxeSmmDriverEntryPoint|IntelFrameworkPkg/Library/DxeSmmDriverEntryPoint/DxeSmmDriverEntryPoint.inf + + # + # Basic + # + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf +!if $(SSE2_ENABLE) == TRUE + BaseMemoryLib|MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.inf +!else + BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf +!endif + 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 + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf +!if $(RC_BINARY_RELEASE) == TRUE + PchPlatformLib|Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLib.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 + 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 + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + GenericBdsLib|$(PLATFORM_PACKAGE)/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf + PlatformBdsLib|$(PLATFORM_PACKAGE)/Library/PlatformBdsLib/PlatformBdsLib.inf + NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf + DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf + FlashDeviceLib|$(PLATFORM_PACKAGE)/Library/FlashDeviceLib/FlashDeviceLib.inf + # + # Framework + # +!if $(S3_ENABLE) == TRUE + S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf +!else + S3BootScriptLib|MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf +!endif + S3IoLib|MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf + S3PciLib|MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf + + # + # Generic Modules + # +!if $(USB_ENABLE) == TRUE + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf +!endif +!if $(SCSI_ENABLE) == TRUE + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf +!endif +!if $(NETWORK_ENABLE) == TRUE + NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf + IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf + UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf + TcpIoLib|MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf + DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf +!endif +!if $(S3_ENABLE) == TRUE + S3Lib|IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf +!endif + + OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf +!if $(CAPSULE_ENABLE) == TRUE + CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf +!else + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf +!endif + LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + IoApicLib|PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + + # + # CPU + # + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf + LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf + CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf + + # + # ICH + # + SmbusLib|$(PLATFORM_PACKAGE)/Library/SmbusLib/SmbusLib.inf + SmmLib|$(PLATFORM_PACKAGE)/Library/PchSmmLib/PchSmmLib.inf + + # + # Platform + # + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf + ResetSystemLib|$(PLATFORM_PACKAGE)/Library/ResetSystemLib/ResetSystemLib.inf + + PlatformCmosLib|$(PLATFORM_PACKAGE)/Library/PlatformCmosLib/PlatformCmosLib.inf + + # + # Misc + # + MonoStatusCodeLib|$(PLATFORM_PACKAGE)/MonoStatusCode/MonoStatusCode.inf +!if $(TARGET) == RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf +!else + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf +!endif + + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf +!if $(TPM_ENABLED) == TRUE + TpmCommLib|SecurityPkg/Library/TpmCommLib/TpmCommLib.inf + Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf + DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf + PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf + SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf +!else + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf +!endif + + # + # CryptLib + # +!if $(TPM_ENABLED) == TRUE + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf +!endif + + BiosIdLib|$(PLATFORM_PACKAGE)/Library/BiosIdLib/BiosIdLib.inf + CpuIA32Lib|$(PLATFORM_PACKAGE)/Library/CpuIA32Lib/CpuIA32Lib.inf + + StallSmmLib|$(PLATFORM_PACKAGE)/Library/StallSmmLib/StallSmmLib.inf + + !if $(SECURE_BOOT_ENABLE) == TRUE + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf + !endif +!if $(RC_BINARY_RELEASE) == TRUE + I2cLib|Vlv2TbltDevicePkg/Library/I2CLib/I2CLibNull.inf +!endif + ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf + + TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf + TrEEPhysicalPresenceLib|SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.inf + Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf +!if $(MINNOW2_FSP_BUILD) == TRUE + FspApiLib|IntelFspWrapperPkg/Library/BaseFspApiLib/BaseFspApiLib.inf + FspPlatformInfoLib|IntelFspWrapperPkg/Library/BaseFspPlatformInfoLibSample/BaseFspPlatformInfoLibSample.inf + FspPlatformSecLib|Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/FspPlatformSecLibVlv2.inf + FspHobProcessLib|Vlv2TbltDevicePkg/FspSupport/Library/PeiFspHobProcessLibVlv2/FspHobProcessLibVlv2.inf +!endif + +[LibraryClasses.IA32.SEC] +!if $(PERFORMANCE_ENABLE) == TRUE + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf +!endif + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + +[LibraryClasses.IA32.PEIM, LibraryClasses.IA32.PEI_CORE, LibraryClasses.IA32.SEC] + # + # PEI phase common + # + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.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 + MultiPlatformLib|$(PLATFORM_PACKAGE)/Library/MultiPlatformLib/MultiPlatformLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf + + +!if $(PERFORMANCE_ENABLE) == TRUE + PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf + TimerLib|PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.inf +!endif + +!if $(TARGET) == RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf +!else + DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf +!endif + + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + + !if $(MINNOW2_FSP_BUILD) == TRUE + PlatformFspLib|Vlv2TbltDevicePkg/Library/PlatformFspLib/PlatformFspLib.inf + !endif + + + +[LibraryClasses.IA32] + # + # DXE phase common + # + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + + TcgPhysicalPresenceLib|SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.inf +!if $(TPM_ENABLED) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +!endif + + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf + EfiRegTableLib|$(PLATFORM_PACKAGE)/Library/EfiRegTableLib/EfiRegTableLib.inf + +!if $(SECURE_BOOT_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +!endif + + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf + +[LibraryClasses.IA32.DXE_DRIVER] + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf +!if $(PERFORMANCE_ENABLE) == TRUE + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + TimerLib|PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + +[LibraryClasses.IA32.DXE_CORE] + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf +!if $(PERFORMANCE_ENABLE) == TRUE + PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf + TimerLib|PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + 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 + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf + !if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf +!endif + CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf + +[LibraryClasses.IA32.SMM_CORE] + MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf + SmmServicesTableLib|MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf + SmmCorePlatformHookLib|MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf + +!if $(TPM_ENABLED) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf +!endif + + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf +!endif + +[LibraryClasses.IA32.DXE_RUNTIME_DRIVER] + ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf +!if $(SECURE_BOOT_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf +!endif +!if $(TPM_ENABLED) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + +[LibraryClasses.common.UEFI_DRIVER] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + +[LibraryClasses.IA32.UEFI_APPLICATION] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + + +################################################################################ +# +# Library Section - list of all EDK/Framework libraries +# +################################################################################ +[Libraries.common] + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseLib/BaseLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseMemoryLib/BaseMemoryLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePrintLib/BasePrintLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseDebugLibNull/BaseDebugLibNull.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePciCf8Lib/BasePciCf8Lib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePciExpressLib/BasePciExpressLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePciLibCf8/BasePciLibCf8.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePeCoffLib/BasePeCoffLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/SmmRuntimeDxeReportStatusCodeLib/SmmRuntimeDxeReportStatusCodeLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiHobLib/PeiHobLib.inf + EdkCompatibilityPkg/Foundation/Ppi/EdkPpiLib.inf + EdkCompatibilityPkg/Foundation/Library/Pei/PeiLib/PeiLib.inf + EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf + EdkCompatibilityPkg/Foundation/Guid/EdkGuidLib.inf + EdkCompatibilityPkg/Foundation/Efi/Protocol/EfiProtocolLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/EfiDriverLib/EfiDriverLib.inf + EdkCompatibilityPkg/Foundation/Protocol/EdkProtocolLib.inf + EdkCompatibilityPkg/Foundation/Framework/Protocol/EdkFrameworkProtocolLib.inf +[Libraries.IA32] + EdkCompatibilityPkg/Foundation/Efi/Guid/EfiGuidLib.inf + EdkCompatibilityPkg/Foundation/Framework/Guid/EdkFrameworkGuidLib.inf + EdkCompatibilityPkg/Foundation/Library/EfiCommonLib/EfiCommonLib.inf + EdkCompatibilityPkg/Foundation/Cpu/Pentium/CpuIA32Lib/CpuIA32Lib.inf + EdkCompatibilityPkg/Foundation/Library/CompilerStub/CompilerStubLib.inf + EdkCompatibilityPkg/Foundation/Framework/Ppi/EdkFrameworkPpiLib.inf + EdkCompatibilityPkg/Foundation/Library/Pei/Hob/PeiHobLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointerLibMm7.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiServicesLib/PeiServicesLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf + EdkCompatibilityPkg/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.inf + + $(PLATFORM_PACKAGE)/Library/MultiPlatformLib/MultiPlatformLib.inf +[Libraries.IA32] + + EdkCompatibilityPkg/Foundation/Efi/Guid/EfiGuidLib.inf + EdkCompatibilityPkg/Foundation/Framework/Guid/EdkFrameworkGuidLib.inf + EdkCompatibilityPkg/Foundation/Library/EfiCommonLib/EfiCommonLib.inf + EdkCompatibilityPkg/Foundation/Cpu/Pentium/CpuIA32Lib/CpuIA32Lib.inf + EdkCompatibilityPkg/Foundation/Library/CompilerStub/CompilerStubLib.inf + EdkCompatibilityPkg/Foundation/Framework/Ppi/EdkFrameworkPpiLib.inf + EdkCompatibilityPkg/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/Hob/HobLib.inf + EdkCompatibilityPkg/Foundation/Library/RuntimeDxe/EfiRuntimeLib/EfiRuntimeLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/EfiIfrSupportLib/EfiIfrSupportLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/Print/PrintLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/EfiScriptLib/EfiScriptLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/PrintLite/PrintLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/GraphicsLite/Graphics.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiLib/UefiLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/DxeHobLib/DxeHobLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/HiiLib/HiiLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiDevicePathLib/UefiDevicePathLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiDriverModelLib/UefiDriverModelLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/DxeServicesTableLib/DxeServicesTableLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/EdkDxeRuntimeDriverLib/EdkDxeRuntimeDriverLib.inf + + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ +[PcdsFeatureFlag.common] +!if $(MINI_BIOS_ENABLE) == FALSE + gPlatformModuleTokenSpaceGuid.PcdBdsDispatchAdditionalOprom|TRUE +!else + gPlatformModuleTokenSpaceGuid.PcdBdsDispatchAdditionalOprom|FALSE +!endif +# +# If PcdDxeIplSwitchToLongMode is TRUE, DxeIpl will load a 64-bit DxeCore and switch to long mode to hand over to DxeCore. +# + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE + + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserGrayOutTextStatement|TRUE + +!if $(CAPSULE_RESET_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|TRUE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|FALSE +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport|TRUE + gEfiCpuTokenSpaceGuid.PcdCpuSmmEnableBspElection|FALSE +!if $(DATAHUB_STATUS_CODE_ENABLE) == TRUE + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub|TRUE +!else + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub|FALSE +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst|FALSE +!if $(TARGET) == RELEASE + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE +!if $(ISA_SERIAL_STATUS_CODE_ENABLE) == TRUE + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseIsaSerial|TRUE +!else + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseIsaSerial|FALSE +!endif +!if $(USB_SERIAL_STATUS_CODE_ENABLE) == TRUE + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseUsbSerial|TRUE +!else + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseUsbSerial|FALSE +!endif +!if $(RAM_SERIAL_STATUS_CODE_ENABLE) == TRUE + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseRam|TRUE +!else + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseRam|FALSE +!endif + + + ## This PCD specifies whether PS2 keyboard does a extended verification during start. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification|FALSE + + ## This PCD specifies whether PS2 mouse does a extended verification during start. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2MouseExtendedVerification|FALSE + +!if $(VARIABLE_INFO_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics|TRUE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics|FALSE +!endif + + gEfiCpuTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp|TRUE + +[PcdsFixedAtBuild.common] +!if $(MINNOW2_FSP_BUILD) == TRUE +# $(FLASH_REGION_VLVMICROCODE_BASE) + gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchAddress|0xFFE00000 +# $(FLASH_REGION_VLVMICROCODE_SIZE) + gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize|0x00030000 + gFspWrapperTokenSpaceGuid.PcdFlashMicroCodeOffset|0x60 +# $(FLASH_AREA_BASE_ADDRESS) + gFspWrapperTokenSpaceGuid.PcdFlashCodeCacheAddress|0xFF800000 +# $(FLASH_AREA_SIZE) + gFspWrapperTokenSpaceGuid.PcdFlashCodeCacheSize|0x00800000 +# $(FLASH_REGION_FSPBIN_BASE) + gFspWrapperTokenSpaceGuid.PcdFlashFvFspBase|0xFFDB0000 +!endif + +!if $(PERFORMANCE_ENABLE) == TRUE +!if $(MINNOW2_FSP_BUILD) == TRUE + # in FSP, when this got used, the memory already is up + gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0x00080000 +!else + gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0xFEF80000 +!endif + gEfiCpuTokenSpaceGuid.PcdTemporaryRamSize|0x00010000 + +!else + !if $(MINNOW2_FSP_BUILD) == TRUE + gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0x00080000 + !else + gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0xFEF80000 + !endif + gEfiCpuTokenSpaceGuid.PcdTemporaryRamSize|0x00010000 + gEfiCpuTokenSpaceGuid.PcdPeiTemporaryRamStackSize|0x3C00 +!endif + + +!if $(SECURE_BOOT_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x22000 +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x4000 +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize|0x00000800 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x400 + gEfiCpuTokenSpaceGuid.PcdCpuIEDRamSize|0x400000 + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize|0x10000 + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeimPerFv|50 + gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPpiSupported|128 + gEfiCpuTokenSpaceGuid.PcdCpuSmmApSyncTimeout|1000 +!if $(S4_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|TRUE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE +!endif +!if $(TARGET) == RELEASE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x3 +!else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 +!endif +!if $(PERFORMANCE_ENABLE) == TRUE + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0x1 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|60 +!endif + + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize|0x10000 + gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable|$(TOP_MEMORY_ADDRESS) + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserSubtitleTextColor|0x0 + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextColor|0x01 + gEfiCpuTokenSpaceGuid.PcdCpuIEDEnabled|TRUE + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable|TRUE + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable|TRUE + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl|FALSE +!endif + +[PcdsFixedAtBuild.IA32.PEIM, PcdsFixedAtBuild.IA32.PEI_CORE, PcdsFixedAtBuild.IA32.SEC] +!if $(TARGET) == RELEASE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x3 +!else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2E + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 +!endif + +[PcdsPatchableInModule.common] + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x803805c6 + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0x$(PLATFORM_PCIEXPRESS_BASE) + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion|FALSE + + ## This PCD specifies whether to use the optimized timing for best PS2 detection performance. + # Note this PCD could be set to TRUE for best boot performance and set to FALSE for best device compatibility. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFastPS2Detection|TRUE + +[PcdsDynamicHii.common.DEFAULT] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|5 # Variable: L"Timeout" + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|L"HwErrRecSupport"|gEfiGlobalVariableGuid|0x0|1 # Variable: L"HwErrRecSupport" + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState|L"BootState"|gEfiBootStateGuid|0x0|TRUE + +[PcdsDynamicDefault.common.DEFAULT] + gEfiMdeModulePkgTokenSpaceGuid.PcdS3BootScriptTablePrivateDataPtr|0x0 + !if $(TPM_ENABLED) == TRUE + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x7b, 0x3a, 0xcd, 0x72, 0xA5, 0xFE, 0x5e, 0x4f, 0x91, 0x65, 0x4d, 0xd1, 0x21, 0x87, 0xbb, 0x13} + !endif + + ## This PCD defines the video horizontal resolution. + # This PCD could be set to 0 then video resolution could be at highest resolution. + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|0 + ## This PCD defines the video vertical resolution. + # This PCD could be set to 0 then video resolution could be at highest resolution. + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|0 + + ## This PCD defines the Console output column and the default value is 25 according to UEFI spec. + # This PCD could be set to 0 then console output could be at max column and max row. + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|31 + ## This PCD defines the Console output row and the default value is 80 according to UEFI spec. + # This PCD could be set to 0 then console output could be at max column and max row. + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|100 + + ## The PCD is used to specify the video horizontal resolution of text setup. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|800 + ## The PCD is used to specify the video vertical resolution of text setup. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|600 + ## The PCD is used to specify the console output column of text setup. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupConOutColumn|100 + ## The PCD is used to specify the console output column of text setup. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupConOutRow|31 + +!if $(TPM_ENABLED) == TRUE + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInitializationPolicy|1 + gEfiSecurityPkgTokenSpaceGuid.PcdTpmScrtmPolicy|1 +!endif + +[PcdsDynamicExDefault.common.DEFAULT] + gEfiVLVTokenSpaceGuid.PcdTCSmbaIoBaseAddress|0x1040 + gEfiVLVTokenSpaceGuid.PcdEmmcManufacturerId|0 + gEfiVLVTokenSpaceGuid.PcdProductSerialNumber|0 + gEfiVLVTokenSpaceGuid.PcdMeasuredBootEnable|TRUE + gEfiVLVTokenSpaceGuid.PcdFTPMErrorOccur|FALSE + gEfiVLVTokenSpaceGuid.PcdFTPMErrorSkip|FALSE + gEfiVLVTokenSpaceGuid.PcdFTPMCommand|0 + gEfiVLVTokenSpaceGuid.PcdFTPMResponse|0 + gEfiVLVTokenSpaceGuid.PcdFTPMNotRespond|FALSE + gEfiVLVTokenSpaceGuid.PcdFTPMStatus|0 + +[Components.IA32] + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf + + !if $(MINNOW2_FSP_BUILD) == TRUE + IntelFspWrapperPkg/FspWrapperSecCore/FspWrapperSecCore.inf { + !if $(TARGET) == DEBUG + + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + } + Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.inf + IntelFspWrapperPkg/FspInitPei/FspInitPei.inf { + !if $(TARGET) == DEBUG + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + } + !endif + + MdeModulePkg/Core/Pei/PeiMain.inf { +!if $(TARGET) == DEBUG + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2E +!endif + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + } + + $(PLATFORM_PACKAGE)/MonoStatusCode/MonoStatusCode.inf { +!if $(TARGET) == DEBUG + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2E +!endif + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MemoryInit.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + } + +!if $(RC_BINARY_RELEASE) == TRUE + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SeCUma.inf +!endif + +!if $(RC_BINARY_RELEASE) == TRUE + $(PLATFORM_PACKAGE)/PlatformPei/PlatformPei.inf { + + *_*_IA32_CC_FLAGS = /DRC_BINARY_RELEASE + !if $(TARGET) == DEBUG + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2E + !endif + } +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + SourceLevelDebugPkg/DebugAgentPei/DebugAgentPei.inf{ + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf + PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf + SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf + } +!endif + + +!if $(TPM_ENABLED) == TRUE + SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf + SecurityPkg/Tcg/TcgPei/TcgPei.inf { + + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf +} +!endif + + $(PLATFORM_PACKAGE)/PlatformInitPei/PlatformInitPei.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x803805c6 + +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!endif + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + } + $(PLATFORM_PACKAGE)/FvInfoPei/FvInfoPei.inf + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/VlvInitPeim.inf +!if $(PCIESC_ENABLE) == TRUE + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchEarlyInitPeim.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + } +!endif + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchInitPeim.inf + + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchSmbusArpDisabled.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchSpiPeim.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PeiSmmAccess.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PeiSmmControl.inf + MdeModulePkg/Universal/PCD/Pei/Pcd.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/CpuPeim.inf + UefiCpuPkg/CpuIoPei/CpuIoPei.inf + UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf + EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf +!if $(CAPSULE_ENABLE) == TRUE + MdeModulePkg/Universal/CapsulePei/CapsulePei.inf +!endif + MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf { + +!if $(LZMA_ENABLE) == TRUE + NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf +!endif + } + +!if $(SECURE_BOOT_ENABLE) == TRUE + SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf +!else + MdeModulePkg/Universal/Variable/Pei/VariablePei.inf +!endif + MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf + +!if $(TPM_ENABLED) == TRUE + SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf { + + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + } +!endif +!if $(ACPI50_ENABLE) == TRUE + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf{ + + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf + } + +!endif +!if $(PERFORMANCE_ENABLE) == TRUE + MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf +!endif +[Components.IA32] + !if $(MINNOW2_FSP_BUILD) == TRUE + IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.inf { + !if $(TARGET) == DEBUG + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + } + + !endif + # + # EDK II Related Platform codes + # + MdeModulePkg/Core/Dxe/DxeMain.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + +!if $(DXE_CRC32_SECTION_ENABLE) == TRUE + NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf +!endif +!if $(LZMA_ENABLE) == TRUE + NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf +!endif +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!endif + } + IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x27 + + !if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + + ICC:*_*_*_CC_FLAGS = /D MDEPKG_NDEBUG + GCC:*_*_*_CC_FLAGS = -D MDEPKG_NDEBUG + } + MdeModulePkg/Universal/PCD/Dxe/Pcd.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf + UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf +!if $(PERFORMANCE_ENABLE) == TRUE + MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf +!endif + MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf { + +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!endif + } + +!if $(CAPSULE_ENABLE) == TRUE + MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf { + + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + } +!endif + + MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf{ + +!if $(SECURE_BOOT_ENABLE) == TRUE + NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf +!endif +!if $(USER_IDENTIFICATION_ENABLE) + NULL|SecurityPkg/Library/DxeDeferImageLoadLib/DxeDeferImageLoadLib.inf +!endif +!if $(TPM_ENABLED) == TRUE + NULL|SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf +!endif + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MpCpu.inf + $(PLATFORM_PACKAGE)/Metronome/Metronome.inf + + IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf{ + + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + PlatformBdsLib|$(PLATFORM_PACKAGE)/Library/PlatformBdsLib/PlatformBdsLib.inf + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf + } + + $(PLATFORM_PACKAGE)/UiApp/UiApp.inf + + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf +!if $(SECURE_BOOT_ENABLE) == TRUE + SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf + SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf{ + + PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf + } + $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbSmm.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiSmm.inf + SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf { + + PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf + + # + # Specify GUID gEfiIfrBootMaintenanceGuid, to install Secure Boot Configuration menu + # into Boot Maintenance Manager menu + # + *_*_*_VFR_FLAGS = -g b2dedc91-d59f-48d2-898a-12490c74a4e0 + } + !else + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf + $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbSmm.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiSmm.inf +!endif + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf { + + FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + } + + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + + $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbRuntimeDxe.inf + + $(PLATFORM_PACKAGE)/PlatformSetupDxe/PlatformSetupDxe.inf + +!if $(DATAHUB_ENABLE) == TRUE + IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|0 + } +!endif + IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf + MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchS3SupportDxe.inf + !if $(USE_HPET_TIMER) == TRUE + PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf + !else + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmartTimer.inf + !endif + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmmControl.inf + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSmbusDxe.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/IntelPchLegacyInterrupt.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchReset.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchInitDxe.inf{ + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSmiDispatcher.inf + +!if $(PCIESC_ENABLE) == TRUE + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchPcieSmm.inf +!endif + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiRuntime.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchPolicyInitDxe.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchBiosWriteProtect.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmmAccess.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PciHostBridge.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/VlvInitDxe.inf + + IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf + + Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInitDxe.inf{ + +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!endif + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/Dptf.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PnpDxe.inf + +!if $(TPM_ENABLED) == TRUE + SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf { + + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + } + + SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf { + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + + # + # specify GUID gEfiIfrNotInTPVPageGuid, this page will not + # be showed in TPV page. + # + *_*_*_VFR_FLAGS = -g e58809f8-fbc1-48e2-883a-a30fdc4b441e + } + + SecurityPkg/Tcg/TcgDxe/TcgDxe.inf { + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + SecurityPkg/Tcg/TcgSmm/TcgSmm.inf +!endif + # + # EDK II Related Platform codes + # + $(PLATFORM_PACKAGE)/PlatformSmm/PlatformSmm.inf{ + + !if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + $(PLATFORM_PACKAGE)/PlatformInfoDxe/PlatformInfoDxe.inf + $(PLATFORM_PACKAGE)/PlatformCpuInfoDxe/PlatformCpuInfoDxe.inf + $(PLATFORM_PACKAGE)/PlatformDxe/PlatformDxe.inf + + $(PLATFORM_PACKAGE)/PciPlatform/PciPlatform.inf + $(PLATFORM_PACKAGE)/SaveMemoryConfig/SaveMemoryConfig.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PlatformCpuPolicy.inf + $(PLATFORM_PACKAGE)/PpmPolicy/PpmPolicy.inf + $(PLATFORM_PACKAGE)/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.inf +!if $(GOP_DRIVER_ENABLE) == TRUE + $(PLATFORM_PACKAGE)/PlatformGopPolicy/PlatformGopPolicy.inf + +!endif + + + # + # SMM + # + MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf + MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PiSmmCpuDxeSmm.inf + UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf + MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PiSmmCommunicationSmm.inf + $(PLATFORM_PACKAGE)/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PowerManagement2.inf + + # + # ACPI + # + MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x27 + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + + $(PLATFORM_PACKAGE)/BootScriptSaveDxe/BootScriptSaveDxe.inf + IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf + Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/PowerManagementAcpiTables.inf + + $(PLATFORM_RC_PACKAGE)/AcpiTablesPCAT/AcpiTables.inf + + $(PLATFORM_PACKAGE)/AcpiPlatform/AcpiPlatform.inf + + # + # PCI + # + MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/ISPDxe.inf + + +# +# ISA +# + $(PLATFORM_PACKAGE)/Wpce791/Wpce791.inf + IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf + IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf + IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf + IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf + IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf +# +# SDIO +# + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MmcHost.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MmcMediaDevice.inf +!if $(ACPI50_ENABLE) == TRUE + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf { + + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf + } + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf { + + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf + } +!endif + +# +# IDE/SCSI/AHCI +# + MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf + IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf +!if $(SATA_ENABLE) == TRUE + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SataController.inf +!endif + MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +!if $(SCSI_ENABLE) == TRUE + MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf +!endif +# +# Console +# + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf + MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + + # + # USB + # +!if $(USB_ENABLE) == TRUE + MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf + MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf + MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf + MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf + MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + +!endif + + # + # ECP + # + EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/FrameworkHiiOnUefiHiiThunk.inf + EdkCompatibilityPkg/Compatibility/LegacyRegion2OnLegacyRegionThunk/LegacyRegion2OnLegacyRegionThunk.inf + EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.inf + EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.inf + EdkCompatibilityPkg/Compatibility/SmmAccess2OnSmmAccessThunk/SmmAccess2OnSmmAccessThunk.inf + EdkCompatibilityPkg/Compatibility/SmmControl2OnSmmControlThunk/SmmControl2OnSmmControlThunk.inf + EdkCompatibilityPkg/Compatibility/FrameworkSmmStatusCodeOnPiSmmStatusCodeThunk/FrameworkSmmStatusCodeOnPiSmmStatusCodeThunk.inf + EdkCompatibilityPkg/Compatibility/FvOnFv2Thunk/FvOnFv2Thunk.inf + # + # SMBIOS + # + MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + $(PLATFORM_PACKAGE)/SmBiosMiscDxe/SmBiosMiscDxe.inf + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmbiosMemory.inf + # + # CPU/FW Microde + # + Vlv2MiscBinariesPkg/Microcode/MicrocodeUpdates.inf { + + *_*_*_GENFW_FLAGS = -a 0x800 -p 0xFF + } + + + PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf + + +!if $(NETWORK_ENABLE) == TRUE + !if $(NETWORK_ISCSI_ENABLE) == TRUE + !if $(NETWORK_IP6_ENABLE) == TRUE + NetworkPkg/IScsiDxe/IScsiDxe.inf + !else + MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf + !endif + !endif + !if $(NETWORK_VLAN_ENABLE) == TRUE + MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf + !endif + !if $(CSM_ENABLE) == TRUE + IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf + !endif +!endif + +!if $(NETWORK_ENABLE) == TRUE + # + # UEFI network modules + # + MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf + MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf + + MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf + MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf + MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf + MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf + MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf + MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf + MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000 + } + MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf + !if $(NETWORK_IP6_ENABLE) == TRUE + NetworkPkg/Ip6Dxe/Ip6Dxe.inf + NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf + NetworkPkg/IpSecDxe/IpSecDxe.inf + NetworkPkg/TcpDxe/TcpDxe.inf + NetworkPkg/Udp6Dxe/Udp6Dxe.inf + NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf + !endif + !if $(NETWORK_IP6_ENABLE) == TRUE + NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf + !else + MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf + !endif +!endif + + Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf + +[BuildOptions] +# +# Define Build Options both for EDK and EDKII drivers. +# + +# +# Define token for different Platform +# +!if $(MINNOW2_FSP_BUILD) == TRUE + DEFINE MINNOW2_FSP_OPTION = /DMINNOW2_FSP_BUILD +!else + DEFINE MINNOW2_FSP_OPTION = +!endif + +!if $(ENBDT_PF_BUILD) == TRUE + DEFINE ENBDT_PF_ENABLE = /DENBDT_PF_ENABLE=1 +!else + DEFINE ENBDT_PF_ENABLE = /DENBDT_PF_ENABLE=0 +!endif + + +!if $(CLKGEN_CONFIG_EXTRA_ENABLE) == TRUE + DEFINE CLKGEN_CONFIG_EXTRA_BUILD_OPTION = /DCLKGEN_CONFIG_EXTRA=1 +!else + DEFINE CLKGEN_CONFIG_EXTRA_BUILD_OPTION = +!endif + + + +!if $(PCIESC_ENABLE) == TRUE + DEFINE PCIESC_SUPPORT_BUILD_OPTION = /DPCIESC_SUPPORT=1 +!else + DEFINE PCIESC_SUPPORT_BUILD_OPTION = +!endif +!if $(SATA_ENABLE) == TRUE + DEFINE SATA_SUPPORT_BUILD_OPTION = /DSATA_SUPPORT=1 +!else + DEFINE SATA_SUPPORT_BUILD_OPTION = +!endif +!if $(ENBDT_S3_SUPPORT) == TRUE + DEFINE ENBDT_S3_SUPPORT_OPTIONS = /DNOCS_S3_SUPPORT +!else + DEFINE ENBDT_S3_SUPPORT_OPTIONS = +!endif + +!if $(X64_CONFIG) == TRUE + DEFINE X64_BUILD_ENABLE = /DX64_BUILD_ENABLE=1 +!else + DEFINE X64_BUILD_ENABLE = +!endif + +!if $(TPM_ENABLED) == TRUE + DEFINE DSC_TPM_BUILD_OPTIONS = /DTPM_ENABLED +!else + DEFINE DSC_TPM_BUILD_OPTIONS = +!endif + + + DEFINE EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS = $(MINNOW2_FSP_OPTION) $(MINNOW2_BUILD_OPTION) $(ENBDT_PF_ENABLE) $(EXTERNAL_VGA_BUILD_OPTION) $(PCIE_ENUM_WA_BUILD_OPTION) $(X0_WA_ENABLE_BUILD_OPTION) $(A0_WA_ENABLE_BUILD_OPTION) $(MICROCODE_FREE_BUILD_OPTIONS) $(SIMICS_BUILD_OPTIONS) $(HYBRID_BUILD_OPTIONS) $(COMPACT_BUILD_OPTIONS) $(VP_BUILD_OPTIONS) $(SYSCTL_ID_BUILD_OPTION) $(CLKGEN_CONFIG_EXTRA_BUILD_OPTION) $(SYSCTL_X0_CONVERT_BOARD_OPTION) $(ENBDT_S3_SUPPORT_OPTIONS) $(SATA_SUPPORT_BUILD_OPTION) $(PCIESC_SUPPORT_BUILD_OPTION) $(DSC_FTPM_ERROR_WR_BUILD_OPTIONS) $(DSC_TPM_BUILD_OPTIONS) $(DSC_BYTI_SECURE_BOOT_BUILD_OPTIONS) +!if $(PERFORMANCE_ENABLE) == TRUE + DEFINE PDB_BUILD_OPTION = /Zi +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + MSFT:*_*_X64_GENFW_FLAGS = --keepexceptiontable + GCC:*_*_X64_GENFW_FLAGS = --keepexceptiontable + INTEL:*_*_X64_GENFW_FLAGS = --keepexceptiontable +!if $(TARGET) == DEBUG + DEFINE SOURCE_LEVEL_DEBUG_BUILD_OPTIONS = /Od /Oy- +!endif +!else + DEFINE SOURCE_LEVEL_DEBUG_BUILD_OPTIONS = + +!endif + +[BuildOptions.Common.EDK] + +# +# Define token for different Platform +# +!if $(ENBDT_PF_BUILD) == TRUE + DEFINE ENBDT_PF_ENABLE = /DENBDT_PF_ENABLE=1 +!else + DEFINE ENBDT_PF_ENABLE = /DENBDT_PF_ENABLE=0 +!endif + +!if $(PERFORMANCE_ENABLE) == TRUE + RELEASE_*_*_DLINK_FLAGS = /DEBUG +!endif + +!if $(S3_ENABLE) == TRUE + DEFINE DSC_S3_BUILD_OPTIONS = /DEFI_S3_RESUME +!else + DEFINE DSC_S3_BUILD_OPTIONS = +!endif + +!if $(ENBDT_S3_SUPPORT) == TRUE + DEFINE ENBDT_S3_SUPPORT_OPTIONS = /DNOCS_S3_SUPPORT +!else + DEFINE ENBDT_S3_SUPPORT_OPTIONS = +!endif + +!if $(X64_CONFIG) == TRUE + DEFINE X64_BUILD_ENABLE = /DX64_BUILD_ENABLE=1 +!else + DEFINE X64_BUILD_ENABLE = +!endif + + + DEFINE EDK_GLUE_LIB_DEBUG = + DEFINE DEBUG_BUILD_OPTIONS = /D EFI_DEBUG /D DEBUG_MODE=1 /GL- $(EDK_GLUE_LIB_DEBUG) /DEDKII_GLUE_DebugPrintErrorLevel=(EFI_D_ERROR) + DEFINE EDK_DSC_FEATURE_BUILD_OPTIONS = $(DSC_S3_BUILD_OPTIONS) $(DSC_ACPI_BUILD_OPTIONS) $(DSC_SEC_BUILD_OPTIONS) $(DSC_FTPM_BUILD_OPTIONS) $(DSC_FTPM_ERROR_WR_BUILD_OPTIONS) $(DSC_TPM_BUILD_OPTIONS) $(SOFTSDV_BUILD_OPTIONS) $(SIMICS_BUILD_OPTIONS) $(HYBRID_BUILD_OPTIONS) $(COMPACT_BUILD_OPTIONS) $(VP_BUILD_OPTIONS) $(QT_BUILD_OPTIONS) $(DSC_BYTI_SECURE_BOOT_BUILD_OPTIONS) /D$(PROJECT_SC_CHIPSET) + + DEFINE EDK_DSC_OTHER_BUILD_OPTIONS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) $(SV_BUILD_OPTIONS) $(INTEL_FASTBOOT_BUILD_OPTION) + DEFINE EDK_DSC_GLOBAL_BUILD_OPTIONS = $(ENBDT_PF_ENABLE) $(EDK_DSC_FEATURE_BUILD_OPTIONS) $(EDK_DSC_OTHER_BUILD_OPTIONS) /D EFI_SPECIFICATION_VERSION=0x00020000 /D PI_SPECIFICATION_VERSION=0x00000009 /D TIANO_RELEASE_VERSION=0x00080006 /D SUPPORT_DEPRECATED_PCI_CFG_PPI /D CSM_SMMENTRY_PORT8DATA8 /D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) /D MAX_VARIABLE_SIZE=0x2000 /D EFI_FIRMWARE_VENDOR="L/"INTEL/"" /D EFI_BUILD_VERSION="L/"EDKII/"" /DEFI_PEI_REPORT_STATUS_CODE_ON $(ENBDT_S3_SUPPORT_OPTIONS) + + *_*_IA32_ASM_FLAGS = /DEFI32 /D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h /DNOCS_S3_SUPPORT + DEBUG_*_IA32_CC_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_IA32_CC_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_IA32_VFRPP_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_IA32_VFRPP_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_IA32_APP_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_IA32_APP_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_IA32_PP_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_IA32_PP_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + *_*_IA32_ASLPP_FLAGS = /D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) + *_*_IA32_ASLCC_FLAGS = /D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) + *_*_IA32_ASM16_FLAGS = /D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h + + *_*_X64_ASM_FLAGS = /DEFIX64 /D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h /DNOCS_S3_SUPPORT + DEBUG_*_X64_CC_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_X64_CC_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_X64_VFRPP_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_X64_VFRPP_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_X64_APP_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_X64_APP_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_X64_PP_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_X64_PP_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + *_*_X64_ASLPP_FLAGS = /D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) + *_*_X64_ASLCC_FLAGS = /D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) + *_*_X64_ASM16_FLAGS = /D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h + # *_*_*_BUILD_FLAGS = -s + *_*_*_VFR_FLAGS = -c + *_*_*_BUILD_FLAGS = -c + +[BuildOptions.Common.EDKII] + *_*_IA32_ASM_FLAGS = $(VP_BUILD_OPTIONS) /D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h /DNOCS_S3_SUPPORT + + *_*_IA32_CC_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_IA32_VFRPP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_IA32_APP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_IA32_PP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_IA32_ASLPP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + + *_*_X64_CC_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) $(SOURCE_LEVEL_DEBUG_BUILD_OPTIONS) + *_*_X64_VFRPP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_X64_APP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_X64_PP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_X64_ASLPP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + + +[Components.IA32] + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SysFwUpdateCapsuleDxe.inf + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/I2cBus.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + } + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/I2cHost.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/I2cPortA0Pio.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x00000043 + } + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/I2cMmioDeviceDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x00000043 + } diff --git a/Vlv2TbltDevicePkg/PlatformPkgX64.dsc b/Vlv2TbltDevicePkg/PlatformPkgX64.dsc new file mode 100644 index 0000000000..bbfe471574 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPkgX64.dsc @@ -0,0 +1,1480 @@ +#/** @file +# Platform description. +# +# Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = Vlv2TbltDevicePkg + PLATFORM_GUID = 465B0A0B-7AC1-443b-8F67-7B8DEC145F90 + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + + # + # Set platform specific package/folder name, same as passed from PREBUILD script. + # PLATFORM_PACKAGE would be the same as PLATFORM_NAME as well as package build folder + # DEFINE only takes effect at R9 DSC and FDF. + # + DEFINE PLATFORM_PACKAGE = Vlv2TbltDevicePkg + DEFINE PLATFORM_RC_PACKAGE = Vlv2DeviceRefCodePkg + DEFINE PLATFORM_BINARY_PACKAGE = Vlv2BinaryPkg + OUTPUT_DIRECTORY = Build/$(PLATFORM_PACKAGE) + SUPPORTED_ARCHITECTURES = IA32|X64 + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + + DEFINE CPU_ARCH =ValleyView2 + DEFINE PROJECT_SC_FAMILY =IntelPch + DEFINE PROJECT_SC_ROOT =../$(PLATFORM_RC_PACKAGE)/ValleyView2Soc/SouthCluster + DEFINE PROJECT_VLV_ROOT =../$(PLATFORM_RC_PACKAGE)/ValleyView2Soc/NorthCluster + + DEFINE RC_BINARY_RELEASE = TRUE + # + # Platform On/Off features are defined here + # + # + # Platform Support:: Set only one token except Crestview Hills + # + # 3.BayleyBay + # ENBDT_PF_ENABLE = TRUE + # + !include $(PLATFORM_PACKAGE)/AutoPlatformCFG.txt + !include $(PLATFORM_PACKAGE)/PlatformPkgConfig.dsc + +!if $(X64_CONFIG) == TRUE + DEFINE DXE_ARCHITECTURE = X64 + DEFINE EDK_DXE_ARCHITECTURE = X64 + DEFINE UNDI_DXE_ARCHITECTURE = 64 +!else + DEFINE DXE_ARCHITECTURE = IA32 + DEFINE EDK_DXE_ARCHITECTURE = Ia32 + DEFINE UNDI_DXE_ARCHITECTURE = 32 +!endif + + FLASH_DEFINITION = $(PLATFORM_PACKAGE)/PlatformPkg.fdf +!if $(LFMA_ENABLE) == TRUE + FIX_LOAD_TOP_MEMORY_ADDRESS = 0xFFFFFFFFFFFFFFFF + DEFINE TOP_MEMORY_ADDRESS = 0xFFFFFFFFFFFFFFFF +!else + FIX_LOAD_TOP_MEMORY_ADDRESS = 0x0 + DEFINE TOP_MEMORY_ADDRESS = 0x0 +!endif + + DEFINE PLATFORM_PCIEXPRESS_BASE = 0E0000000 + + +################################################################################ +# +# 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.common] + # + # 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 + DxeSmmDriverEntryPoint|IntelFrameworkPkg/Library/DxeSmmDriverEntryPoint/DxeSmmDriverEntryPoint.inf + + # + # Basic + # + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf +!if $(SSE2_ENABLE) == TRUE + BaseMemoryLib|MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.inf +!else + BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf +!endif + 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 + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf +!if $(RC_BINARY_RELEASE) == TRUE + PchPlatformLib|Vlv2TbltDevicePkg/Library/PchPlatformLib/PchPlatformLib.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 + 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 + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + GenericBdsLib|$(PLATFORM_PACKAGE)/Override/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf + PlatformBdsLib|$(PLATFORM_PACKAGE)/Library/PlatformBdsLib/PlatformBdsLib.inf + NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf + DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf + FlashDeviceLib|$(PLATFORM_PACKAGE)/Library/FlashDeviceLib/FlashDeviceLib.inf + # + # Framework + # +!if $(S3_ENABLE) == TRUE + S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf +!else + S3BootScriptLib|MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf +!endif + S3IoLib|MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf + S3PciLib|MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf + + # + # Generic Modules + # +!if $(USB_ENABLE) == TRUE + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf +!endif +!if $(SCSI_ENABLE) == TRUE + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf +!endif +!if $(NETWORK_ENABLE) == TRUE + NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf + IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf + UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf + TcpIoLib|MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf + DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf +!endif +!if $(S3_ENABLE) == TRUE + S3Lib|IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf +!endif + + OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf +!if $(CAPSULE_ENABLE) == TRUE + CapsuleLib|IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf +!else + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf +!endif + LanguageLib|EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + IoApicLib|PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + + # + # CPU + # + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf + LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf + CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf + + # + # ICH + # + SmbusLib|$(PLATFORM_PACKAGE)/Library/SmbusLib/SmbusLib.inf + SmmLib|$(PLATFORM_PACKAGE)/Library/PchSmmLib/PchSmmLib.inf + + # + # Platform + # + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf + ResetSystemLib|$(PLATFORM_PACKAGE)/Library/ResetSystemLib/ResetSystemLib.inf + + PlatformCmosLib|$(PLATFORM_PACKAGE)/Library/PlatformCmosLib/PlatformCmosLib.inf + + # + # Misc + # + MonoStatusCodeLib|$(PLATFORM_PACKAGE)/MonoStatusCode/MonoStatusCode.inf +!if $(TARGET) == RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf +!else + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf +!endif + + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf +!if $(TPM_ENABLED) == TRUE + TpmCommLib|SecurityPkg/Library/TpmCommLib/TpmCommLib.inf + Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf + DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf + PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf + SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf +!else + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf +!endif + + # + # CryptLib + # +!if $(TPM_ENABLED) == TRUE + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf +!endif + + BiosIdLib|$(PLATFORM_PACKAGE)/Library/BiosIdLib/BiosIdLib.inf + CpuIA32Lib|$(PLATFORM_PACKAGE)/Library/CpuIA32Lib/CpuIA32Lib.inf + + StallSmmLib|$(PLATFORM_PACKAGE)/Library/StallSmmLib/StallSmmLib.inf + + !if $(SECURE_BOOT_ENABLE) == TRUE + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf + !endif +!if $(RC_BINARY_RELEASE) == TRUE + I2cLib|Vlv2TbltDevicePkg/Library/I2CLib/I2CLibNull.inf +!endif + ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf + + TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf + TrEEPhysicalPresenceLib|SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.inf + Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf +!if $(MINNOW2_FSP_BUILD) == TRUE + FspApiLib|IntelFspWrapperPkg/Library/BaseFspApiLib/BaseFspApiLib.inf + FspPlatformInfoLib|IntelFspWrapperPkg/Library/BaseFspPlatformInfoLibSample/BaseFspPlatformInfoLibSample.inf + FspPlatformSecLib|Vlv2TbltDevicePkg/FspSupport/Library/SecFspPlatformSecLibVlv2/FspPlatformSecLibVlv2.inf + FspHobProcessLib|Vlv2TbltDevicePkg/FspSupport/Library/PeiFspHobProcessLibVlv2/FspHobProcessLibVlv2.inf +!endif + +[LibraryClasses.IA32.SEC] +!if $(PERFORMANCE_ENABLE) == TRUE + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf +!endif + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + +[LibraryClasses.IA32.PEIM, LibraryClasses.IA32.PEI_CORE, LibraryClasses.IA32.SEC] + # + # PEI phase common + # + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.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 + MultiPlatformLib|$(PLATFORM_PACKAGE)/Library/MultiPlatformLib/MultiPlatformLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf + + +!if $(PERFORMANCE_ENABLE) == TRUE + PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf + TimerLib|PerformancePkg/Library/TscTimerLib/PeiTscTimerLib.inf +!endif + +!if $(TARGET) == RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf +!else + DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf +!endif + + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + + !if $(MINNOW2_FSP_BUILD) == TRUE + PlatformFspLib|Vlv2TbltDevicePkg/Library/PlatformFspLib/PlatformFspLib.inf + !endif + + + +[LibraryClasses.X64] + # + # DXE phase common + # + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + + TcgPhysicalPresenceLib|SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.inf +!if $(TPM_ENABLED) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +!endif + + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf + EfiRegTableLib|$(PLATFORM_PACKAGE)/Library/EfiRegTableLib/EfiRegTableLib.inf + +!if $(SECURE_BOOT_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +!endif + + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf + +[LibraryClasses.X64.DXE_DRIVER] + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf +!if $(PERFORMANCE_ENABLE) == TRUE + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + TimerLib|PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + +[LibraryClasses.X64.DXE_CORE] + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf +!if $(PERFORMANCE_ENABLE) == TRUE + PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf + TimerLib|PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + +[LibraryClasses.X64.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 + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf + !if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf +!endif + CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf + +[LibraryClasses.X64.SMM_CORE] + MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf + SmmServicesTableLib|MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf + SmmCorePlatformHookLib|MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf + +!if $(TPM_ENABLED) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf +!endif + + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf +!endif + +[LibraryClasses.X64.DXE_RUNTIME_DRIVER] + ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf +!if $(SECURE_BOOT_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf +!endif +!if $(TPM_ENABLED) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + +[LibraryClasses.common.UEFI_DRIVER] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + +[LibraryClasses.X64.UEFI_APPLICATION] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + + +################################################################################ +# +# Library Section - list of all EDK/Framework libraries +# +################################################################################ +[Libraries.common] + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseLib/BaseLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseMemoryLib/BaseMemoryLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePrintLib/BasePrintLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseDebugLibNull/BaseDebugLibNull.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePciCf8Lib/BasePciCf8Lib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePciExpressLib/BasePciExpressLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePciLibCf8/BasePciLibCf8.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePeCoffLib/BasePeCoffLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/SmmRuntimeDxeReportStatusCodeLib/SmmRuntimeDxeReportStatusCodeLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiHobLib/PeiHobLib.inf + EdkCompatibilityPkg/Foundation/Ppi/EdkPpiLib.inf + EdkCompatibilityPkg/Foundation/Library/Pei/PeiLib/PeiLib.inf + EdkCompatibilityPkg/Compatibility/Library/UefiLanguageLib/UefiLanguageLib.inf + EdkCompatibilityPkg/Foundation/Guid/EdkGuidLib.inf + EdkCompatibilityPkg/Foundation/Efi/Protocol/EfiProtocolLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/EfiDriverLib/EfiDriverLib.inf + EdkCompatibilityPkg/Foundation/Protocol/EdkProtocolLib.inf + EdkCompatibilityPkg/Foundation/Framework/Protocol/EdkFrameworkProtocolLib.inf +[Libraries.IA32] + EdkCompatibilityPkg/Foundation/Efi/Guid/EfiGuidLib.inf + EdkCompatibilityPkg/Foundation/Framework/Guid/EdkFrameworkGuidLib.inf + EdkCompatibilityPkg/Foundation/Library/EfiCommonLib/EfiCommonLib.inf + EdkCompatibilityPkg/Foundation/Cpu/Pentium/CpuIA32Lib/CpuIA32Lib.inf + EdkCompatibilityPkg/Foundation/Library/CompilerStub/CompilerStubLib.inf + EdkCompatibilityPkg/Foundation/Framework/Ppi/EdkFrameworkPpiLib.inf + EdkCompatibilityPkg/Foundation/Library/Pei/Hob/PeiHobLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointerLibMm7.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiServicesLib/PeiServicesLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf + EdkCompatibilityPkg/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.inf + + $(PLATFORM_PACKAGE)/Library/MultiPlatformLib/MultiPlatformLib.inf +[Libraries.X64] + + EdkCompatibilityPkg/Foundation/Efi/Guid/EfiGuidLib.inf + EdkCompatibilityPkg/Foundation/Framework/Guid/EdkFrameworkGuidLib.inf + EdkCompatibilityPkg/Foundation/Library/EfiCommonLib/EfiCommonLib.inf + EdkCompatibilityPkg/Foundation/Cpu/Pentium/CpuIA32Lib/CpuIA32Lib.inf + EdkCompatibilityPkg/Foundation/Library/CompilerStub/CompilerStubLib.inf + EdkCompatibilityPkg/Foundation/Framework/Ppi/EdkFrameworkPpiLib.inf + EdkCompatibilityPkg/Foundation/Core/Dxe/ArchProtocol/ArchProtocolLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/Hob/HobLib.inf + EdkCompatibilityPkg/Foundation/Library/RuntimeDxe/EfiRuntimeLib/EfiRuntimeLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/EfiIfrSupportLib/EfiIfrSupportLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/Print/PrintLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/EfiScriptLib/EfiScriptLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/PrintLite/PrintLib.inf + EdkCompatibilityPkg/Foundation/Library/Dxe/GraphicsLite/Graphics.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiLib/UefiLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/DxeHobLib/DxeHobLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/HiiLib/HiiLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiDevicePathLib/UefiDevicePathLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/UefiDriverModelLib/UefiDriverModelLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/DxeServicesTableLib/DxeServicesTableLib.inf + EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/EdkDxeRuntimeDriverLib/EdkDxeRuntimeDriverLib.inf + + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ +[PcdsFeatureFlag.common] +!if $(MINI_BIOS_ENABLE) == FALSE + gPlatformModuleTokenSpaceGuid.PcdBdsDispatchAdditionalOprom|TRUE +!else + gPlatformModuleTokenSpaceGuid.PcdBdsDispatchAdditionalOprom|FALSE +!endif +# +# If PcdDxeIplSwitchToLongMode is TRUE, DxeIpl will load a 64-bit DxeCore and switch to long mode to hand over to DxeCore. +# + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE + + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserGrayOutTextStatement|TRUE + +!if $(CAPSULE_RESET_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|TRUE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|FALSE +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport|TRUE + gEfiCpuTokenSpaceGuid.PcdCpuSmmEnableBspElection|FALSE +!if $(DATAHUB_STATUS_CODE_ENABLE) == TRUE + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub|TRUE +!else + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub|FALSE +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst|FALSE +!if $(TARGET) == RELEASE + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE +!if $(ISA_SERIAL_STATUS_CODE_ENABLE) == TRUE + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseIsaSerial|TRUE +!else + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseIsaSerial|FALSE +!endif +!if $(USB_SERIAL_STATUS_CODE_ENABLE) == TRUE + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseUsbSerial|TRUE +!else + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseUsbSerial|FALSE +!endif +!if $(RAM_SERIAL_STATUS_CODE_ENABLE) == TRUE + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseRam|TRUE +!else + gEfiSerialPortTokenSpaceGuid.PcdStatusCodeUseRam|FALSE +!endif + + + ## This PCD specifies whether PS2 keyboard does a extended verification during start. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification|FALSE + + ## This PCD specifies whether PS2 mouse does a extended verification during start. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPs2MouseExtendedVerification|FALSE + +!if $(VARIABLE_INFO_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics|TRUE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics|FALSE +!endif + + gEfiCpuTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp|TRUE + +[PcdsFixedAtBuild.common] +!if $(MINNOW2_FSP_BUILD) == TRUE +# $(FLASH_REGION_VLVMICROCODE_BASE) + gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchAddress|0xFFE00000 +# $(FLASH_REGION_VLVMICROCODE_SIZE) + gFspWrapperTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize|0x00030000 + gFspWrapperTokenSpaceGuid.PcdFlashMicroCodeOffset|0x60 +# $(FLASH_AREA_BASE_ADDRESS) + gFspWrapperTokenSpaceGuid.PcdFlashCodeCacheAddress|0xFF800000 +# $(FLASH_AREA_SIZE) + gFspWrapperTokenSpaceGuid.PcdFlashCodeCacheSize|0x00800000 +# $(FLASH_REGION_FSPBIN_BASE) + gFspWrapperTokenSpaceGuid.PcdFlashFvFspBase|0xFFDB0000 +!endif + +!if $(PERFORMANCE_ENABLE) == TRUE +!if $(MINNOW2_FSP_BUILD) == TRUE + # in FSP, when this got used, the memory already is up + gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0x00080000 +!else + gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0xFEF80000 +!endif + gEfiCpuTokenSpaceGuid.PcdTemporaryRamSize|0x00010000 + +!else + !if $(MINNOW2_FSP_BUILD) == TRUE + gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0x00080000 + !else + gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0xFEF80000 + !endif + gEfiCpuTokenSpaceGuid.PcdTemporaryRamSize|0x00010000 + gEfiCpuTokenSpaceGuid.PcdPeiTemporaryRamStackSize|0x3C00 +!endif + + +!if $(SECURE_BOOT_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x22000 +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x4000 +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize|0x00000800 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x400 + gEfiCpuTokenSpaceGuid.PcdCpuIEDRamSize|0x400000 + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize|0x10000 + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeimPerFv|50 + gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPpiSupported|128 + gEfiCpuTokenSpaceGuid.PcdCpuSmmApSyncTimeout|1000 +!if $(S4_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|TRUE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE +!endif +!if $(TARGET) == RELEASE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x3 +!else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 +!endif +!if $(PERFORMANCE_ENABLE) == TRUE + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0x1 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|60 +!endif + + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize|0x10000 + gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable|$(TOP_MEMORY_ADDRESS) + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserSubtitleTextColor|0x0 + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextColor|0x01 + gEfiCpuTokenSpaceGuid.PcdCpuIEDEnabled|TRUE + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable|TRUE + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable|TRUE + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl|FALSE +!endif + +[PcdsFixedAtBuild.IA32.PEIM, PcdsFixedAtBuild.IA32.PEI_CORE, PcdsFixedAtBuild.IA32.SEC] +!if $(TARGET) == RELEASE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x3 +!else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2E + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 +!endif + +[PcdsPatchableInModule.common] + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x803805c6 + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0x$(PLATFORM_PCIEXPRESS_BASE) + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion|FALSE + + ## This PCD specifies whether to use the optimized timing for best PS2 detection performance. + # Note this PCD could be set to TRUE for best boot performance and set to FALSE for best device compatibility. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdFastPS2Detection|TRUE + +[PcdsDynamicHii.common.DEFAULT] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|5 # Variable: L"Timeout" + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|L"HwErrRecSupport"|gEfiGlobalVariableGuid|0x0|1 # Variable: L"HwErrRecSupport" + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootState|L"BootState"|gEfiBootStateGuid|0x0|TRUE + +[PcdsDynamicDefault.common.DEFAULT] + gEfiMdeModulePkgTokenSpaceGuid.PcdS3BootScriptTablePrivateDataPtr|0x0 + !if $(TPM_ENABLED) == TRUE + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x7b, 0x3a, 0xcd, 0x72, 0xA5, 0xFE, 0x5e, 0x4f, 0x91, 0x65, 0x4d, 0xd1, 0x21, 0x87, 0xbb, 0x13} + !endif + + ## This PCD defines the video horizontal resolution. + # This PCD could be set to 0 then video resolution could be at highest resolution. + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|0 + ## This PCD defines the video vertical resolution. + # This PCD could be set to 0 then video resolution could be at highest resolution. + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|0 + + ## This PCD defines the Console output column and the default value is 25 according to UEFI spec. + # This PCD could be set to 0 then console output could be at max column and max row. + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|31 + ## This PCD defines the Console output row and the default value is 80 according to UEFI spec. + # This PCD could be set to 0 then console output could be at max column and max row. + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|100 + + ## The PCD is used to specify the video horizontal resolution of text setup. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|800 + ## The PCD is used to specify the video vertical resolution of text setup. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|600 + ## The PCD is used to specify the console output column of text setup. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupConOutColumn|100 + ## The PCD is used to specify the console output column of text setup. + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupConOutRow|31 + +!if $(TPM_ENABLED) == TRUE + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInitializationPolicy|1 + gEfiSecurityPkgTokenSpaceGuid.PcdTpmScrtmPolicy|1 +!endif + +[PcdsDynamicExDefault.common.DEFAULT] + gEfiVLVTokenSpaceGuid.PcdTCSmbaIoBaseAddress|0x1040 + gEfiVLVTokenSpaceGuid.PcdEmmcManufacturerId|0 + gEfiVLVTokenSpaceGuid.PcdProductSerialNumber|0 + gEfiVLVTokenSpaceGuid.PcdMeasuredBootEnable|TRUE + gEfiVLVTokenSpaceGuid.PcdFTPMErrorOccur|FALSE + gEfiVLVTokenSpaceGuid.PcdFTPMErrorSkip|FALSE + gEfiVLVTokenSpaceGuid.PcdFTPMCommand|0 + gEfiVLVTokenSpaceGuid.PcdFTPMResponse|0 + gEfiVLVTokenSpaceGuid.PcdFTPMNotRespond|FALSE + gEfiVLVTokenSpaceGuid.PcdFTPMStatus|0 + +[Components.IA32] + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SecCore.inf + + !if $(MINNOW2_FSP_BUILD) == TRUE + IntelFspWrapperPkg/FspWrapperSecCore/FspWrapperSecCore.inf { + !if $(TARGET) == DEBUG + + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + } + Vlv2TbltDevicePkg/FspSupport/BootModePei/BootModePei.inf + IntelFspWrapperPkg/FspInitPei/FspInitPei.inf { + !if $(TARGET) == DEBUG + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + } + !endif + + MdeModulePkg/Core/Pei/PeiMain.inf { +!if $(TARGET) == DEBUG + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2E +!endif + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + } + + $(PLATFORM_PACKAGE)/MonoStatusCode/MonoStatusCode.inf { +!if $(TARGET) == DEBUG + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2E +!endif + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MemoryInit.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + } + +!if $(RC_BINARY_RELEASE) == TRUE + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/SeCUma.inf +!endif + +!if $(RC_BINARY_RELEASE) == TRUE + $(PLATFORM_PACKAGE)/PlatformPei/PlatformPei.inf { + + *_*_IA32_CC_FLAGS = /DRC_BINARY_RELEASE + !if $(TARGET) == DEBUG + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2E + !endif + } +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + SourceLevelDebugPkg/DebugAgentPei/DebugAgentPei.inf{ + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf + PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf + SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf + } +!endif + + +!if $(TPM_ENABLED) == TRUE + SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf + SecurityPkg/Tcg/TcgPei/TcgPei.inf { + + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf +} +!endif + + $(PLATFORM_PACKAGE)/PlatformInitPei/PlatformInitPei.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x803805c6 + +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!endif + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + } + $(PLATFORM_PACKAGE)/FvInfoPei/FvInfoPei.inf + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/VlvInitPeim.inf +!if $(PCIESC_ENABLE) == TRUE + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchEarlyInitPeim.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + } +!endif + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchInitPeim.inf + + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchSmbusArpDisabled.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PchSpiPeim.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PeiSmmAccess.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PeiSmmControl.inf + MdeModulePkg/Universal/PCD/Pei/Pcd.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/CpuPeim.inf + UefiCpuPkg/CpuIoPei/CpuIoPei.inf + UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/MpS3.inf + EdkCompatibilityPkg/Compatibility/AcpiVariableHobOnSmramReserveHobThunk/AcpiVariableHobOnSmramReserveHobThunk.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/IA32/PiSmmCommunicationPei.inf +!if $(CAPSULE_ENABLE) == TRUE + MdeModulePkg/Universal/CapsulePei/CapsulePei.inf +!endif + MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf { + +!if $(LZMA_ENABLE) == TRUE + NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf +!endif + } + +!if $(SECURE_BOOT_ENABLE) == TRUE + SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf +!else + MdeModulePkg/Universal/Variable/Pei/VariablePei.inf +!endif + MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf + +!if $(TPM_ENABLED) == TRUE + SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf { + + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + } +!endif +!if $(ACPI50_ENABLE) == TRUE + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf{ + + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf + } + +!endif +!if $(PERFORMANCE_ENABLE) == TRUE + MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf +!endif +[Components.X64] + !if $(MINNOW2_FSP_BUILD) == TRUE + IntelFspWrapperPkg/FspNotifyDxe/FspNotifyDxe.inf { + !if $(TARGET) == DEBUG + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + } + + !endif + # + # EDK II Related Platform codes + # + MdeModulePkg/Core/Dxe/DxeMain.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000046 + +!if $(DXE_CRC32_SECTION_ENABLE) == TRUE + NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf +!endif +!if $(LZMA_ENABLE) == TRUE + NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf +!endif +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!endif + } + IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x27 + + !if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + + ICC:*_*_*_CC_FLAGS = /D MDEPKG_NDEBUG + GCC:*_*_*_CC_FLAGS = -D MDEPKG_NDEBUG + } + MdeModulePkg/Universal/PCD/Dxe/Pcd.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf + UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf +!if $(PERFORMANCE_ENABLE) == TRUE + MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf +!endif + MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf { + +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!endif + } + +!if $(CAPSULE_ENABLE) == TRUE + MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf { + + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + } +!endif + + MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf{ + +!if $(SECURE_BOOT_ENABLE) == TRUE + NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf +!endif +!if $(USER_IDENTIFICATION_ENABLE) + NULL|SecurityPkg/Library/DxeDeferImageLoadLib/DxeDeferImageLoadLib.inf +!endif +!if $(TPM_ENABLED) == TRUE + NULL|SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf +!endif + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MpCpu.inf + $(PLATFORM_PACKAGE)/Metronome/Metronome.inf + + IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf{ + + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + PlatformBdsLib|$(PLATFORM_PACKAGE)/Library/PlatformBdsLib/PlatformBdsLib.inf + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf + } + + $(PLATFORM_PACKAGE)/UiApp/UiApp.inf + + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf +!if $(SECURE_BOOT_ENABLE) == TRUE + SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf + SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf{ + + PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf + SerialPortLib|$(PLATFORM_PACKAGE)/Library/SerialPortLib/SerialPortLib.inf + } + $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbSmm.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiSmm.inf + SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf { + + PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf + + # + # Specify GUID gEfiIfrBootMaintenanceGuid, to install Secure Boot Configuration menu + # into Boot Maintenance Manager menu + # + *_*_*_VFR_FLAGS = -g b2dedc91-d59f-48d2-898a-12490c74a4e0 + } + !else + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf + $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbSmm.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiSmm.inf +!endif + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf { + + FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + } + + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + + $(PLATFORM_PACKAGE)/FvbRuntimeDxe/FvbRuntimeDxe.inf + + $(PLATFORM_PACKAGE)/PlatformSetupDxe/PlatformSetupDxe.inf + +!if $(DATAHUB_ENABLE) == TRUE + IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|0 + } +!endif + IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf + MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchS3SupportDxe.inf + !if $(USE_HPET_TIMER) == TRUE + PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf + !else + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmartTimer.inf + !endif + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmmControl.inf + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSmbusDxe.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/IntelPchLegacyInterrupt.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchReset.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchInitDxe.inf{ + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSmiDispatcher.inf + +!if $(PCIESC_ENABLE) == TRUE + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchPcieSmm.inf +!endif + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchSpiRuntime.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchPolicyInitDxe.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PchBiosWriteProtect.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmmAccess.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PciHostBridge.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/VlvInitDxe.inf + + IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf + + Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInitDxe.inf{ + +!if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!endif + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/Dptf.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PnpDxe.inf + +!if $(TPM_ENABLED) == TRUE + SecurityPkg/Tcg/TrEEConfig/TrEEConfigPei.inf { + + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + } + + SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf { + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + + # + # specify GUID gEfiIfrNotInTPVPageGuid, this page will not + # be showed in TPV page. + # + *_*_*_VFR_FLAGS = -g e58809f8-fbc1-48e2-883a-a30fdc4b441e + } + + SecurityPkg/Tcg/TcgDxe/TcgDxe.inf { + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + SecurityPkg/Tcg/TcgSmm/TcgSmm.inf +!endif + # + # EDK II Related Platform codes + # + $(PLATFORM_PACKAGE)/PlatformSmm/PlatformSmm.inf{ + + !if $(TARGET) != RELEASE + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + !endif + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + $(PLATFORM_PACKAGE)/PlatformInfoDxe/PlatformInfoDxe.inf + $(PLATFORM_PACKAGE)/PlatformCpuInfoDxe/PlatformCpuInfoDxe.inf + $(PLATFORM_PACKAGE)/PlatformDxe/PlatformDxe.inf + + $(PLATFORM_PACKAGE)/PciPlatform/PciPlatform.inf + $(PLATFORM_PACKAGE)/SaveMemoryConfig/SaveMemoryConfig.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PlatformCpuPolicy.inf + $(PLATFORM_PACKAGE)/PpmPolicy/PpmPolicy.inf + $(PLATFORM_PACKAGE)/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.inf +!if $(GOP_DRIVER_ENABLE) == TRUE + $(PLATFORM_PACKAGE)/PlatformGopPolicy/PlatformGopPolicy.inf + +!endif + + + # + # SMM + # + MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf + MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PiSmmCpuDxeSmm.inf + UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf + MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PiSmmCommunicationSmm.inf + $(PLATFORM_PACKAGE)/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/PowerManagement2.inf + + # + # ACPI + # + MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x27 + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + + $(PLATFORM_PACKAGE)/BootScriptSaveDxe/BootScriptSaveDxe.inf + IntelFrameworkModulePkg/Universal/Acpi/AcpiSupportDxe/AcpiSupportDxe.inf + Vlv2DeviceRefCodePkg/ValleyView2Soc/CPU/PowerManagement/AcpiTables/PowerManagementAcpiTables.inf + + $(PLATFORM_RC_PACKAGE)/AcpiTablesPCAT/AcpiTables.inf + + $(PLATFORM_PACKAGE)/AcpiPlatform/AcpiPlatform.inf + + # + # PCI + # + MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/ISPDxe.inf + + +# +# ISA +# + $(PLATFORM_PACKAGE)/Wpce791/Wpce791.inf + IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf + IntelFrameworkModulePkg/Bus/Isa/IsaIoDxe/IsaIoDxe.inf + IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf + IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf + IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf +# +# SDIO +# + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MmcHost.inf + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/MmcMediaDevice.inf +!if $(ACPI50_ENABLE) == TRUE + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf { + + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf + } + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf { + + TimerLib|$(PLATFORM_PACKAGE)/Library/IntelPchAcpiTimerLib/IntelPchAcpiTimerLib.inf + } +!endif + +# +# IDE/SCSI/AHCI +# + MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf + IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf +!if $(SATA_ENABLE) == TRUE + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SataController.inf +!endif + MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +!if $(SCSI_ENABLE) == TRUE + MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf +!endif +# +# Console +# + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + Vlv2TbltDevicePkg/Override/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf + MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + + # + # USB + # +!if $(USB_ENABLE) == TRUE + MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf + MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf + MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf + MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf + MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + +!endif + + # + # ECP + # + EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/FrameworkHiiOnUefiHiiThunk.inf + EdkCompatibilityPkg/Compatibility/LegacyRegion2OnLegacyRegionThunk/LegacyRegion2OnLegacyRegionThunk.inf + EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.inf + EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.inf + EdkCompatibilityPkg/Compatibility/SmmAccess2OnSmmAccessThunk/SmmAccess2OnSmmAccessThunk.inf + EdkCompatibilityPkg/Compatibility/SmmControl2OnSmmControlThunk/SmmControl2OnSmmControlThunk.inf + EdkCompatibilityPkg/Compatibility/FrameworkSmmStatusCodeOnPiSmmStatusCodeThunk/FrameworkSmmStatusCodeOnPiSmmStatusCodeThunk.inf + EdkCompatibilityPkg/Compatibility/FvOnFv2Thunk/FvOnFv2Thunk.inf + # + # SMBIOS + # + MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + $(PLATFORM_PACKAGE)/SmBiosMiscDxe/SmBiosMiscDxe.inf + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SmbiosMemory.inf + # + # CPU/FW Microde + # + Vlv2MiscBinariesPkg/Microcode/MicrocodeUpdates.inf { + + *_*_*_GENFW_FLAGS = -a 0x800 -p 0xFF + } + + + PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf + + +!if $(NETWORK_ENABLE) == TRUE + !if $(NETWORK_ISCSI_ENABLE) == TRUE + !if $(NETWORK_IP6_ENABLE) == TRUE + NetworkPkg/IScsiDxe/IScsiDxe.inf + !else + MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf + !endif + !endif + !if $(NETWORK_VLAN_ENABLE) == TRUE + MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf + !endif + !if $(CSM_ENABLE) == TRUE + IntelFrameworkModulePkg/Csm/BiosThunk/Snp16Dxe/Snp16Dxe.inf + !endif +!endif + +!if $(NETWORK_ENABLE) == TRUE + # + # UEFI network modules + # + MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf + MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf + + MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf + MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf + MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf + MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf + MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf + MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf + MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000 + } + MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf + !if $(NETWORK_IP6_ENABLE) == TRUE + NetworkPkg/Ip6Dxe/Ip6Dxe.inf + NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf + NetworkPkg/IpSecDxe/IpSecDxe.inf + NetworkPkg/TcpDxe/TcpDxe.inf + NetworkPkg/Udp6Dxe/Udp6Dxe.inf + NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf + !endif + !if $(NETWORK_IP6_ENABLE) == TRUE + NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf + !else + MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf + !endif +!endif + + Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.inf + +[BuildOptions] +# +# Define Build Options both for EDK and EDKII drivers. +# + +# +# Define token for different Platform +# +!if $(MINNOW2_FSP_BUILD) == TRUE + DEFINE MINNOW2_FSP_OPTION = /DMINNOW2_FSP_BUILD +!else + DEFINE MINNOW2_FSP_OPTION = +!endif + +!if $(ENBDT_PF_BUILD) == TRUE + DEFINE ENBDT_PF_ENABLE = /DENBDT_PF_ENABLE=1 +!else + DEFINE ENBDT_PF_ENABLE = /DENBDT_PF_ENABLE=0 +!endif + + +!if $(CLKGEN_CONFIG_EXTRA_ENABLE) == TRUE + DEFINE CLKGEN_CONFIG_EXTRA_BUILD_OPTION = /DCLKGEN_CONFIG_EXTRA=1 +!else + DEFINE CLKGEN_CONFIG_EXTRA_BUILD_OPTION = +!endif + + + +!if $(PCIESC_ENABLE) == TRUE + DEFINE PCIESC_SUPPORT_BUILD_OPTION = /DPCIESC_SUPPORT=1 +!else + DEFINE PCIESC_SUPPORT_BUILD_OPTION = +!endif +!if $(SATA_ENABLE) == TRUE + DEFINE SATA_SUPPORT_BUILD_OPTION = /DSATA_SUPPORT=1 +!else + DEFINE SATA_SUPPORT_BUILD_OPTION = +!endif +!if $(ENBDT_S3_SUPPORT) == TRUE + DEFINE ENBDT_S3_SUPPORT_OPTIONS = /DNOCS_S3_SUPPORT +!else + DEFINE ENBDT_S3_SUPPORT_OPTIONS = +!endif + +!if $(X64_CONFIG) == TRUE + DEFINE X64_BUILD_ENABLE = /DX64_BUILD_ENABLE=1 +!else + DEFINE X64_BUILD_ENABLE = +!endif + +!if $(TPM_ENABLED) == TRUE + DEFINE DSC_TPM_BUILD_OPTIONS = /DTPM_ENABLED +!else + DEFINE DSC_TPM_BUILD_OPTIONS = +!endif + + + DEFINE EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS = $(MINNOW2_FSP_OPTION) $(MINNOW2_BUILD_OPTION) $(ENBDT_PF_ENABLE) $(EXTERNAL_VGA_BUILD_OPTION) $(PCIE_ENUM_WA_BUILD_OPTION) $(X0_WA_ENABLE_BUILD_OPTION) $(A0_WA_ENABLE_BUILD_OPTION) $(MICROCODE_FREE_BUILD_OPTIONS) $(SIMICS_BUILD_OPTIONS) $(HYBRID_BUILD_OPTIONS) $(COMPACT_BUILD_OPTIONS) $(VP_BUILD_OPTIONS) $(SYSCTL_ID_BUILD_OPTION) $(CLKGEN_CONFIG_EXTRA_BUILD_OPTION) $(SYSCTL_X0_CONVERT_BOARD_OPTION) $(ENBDT_S3_SUPPORT_OPTIONS) $(SATA_SUPPORT_BUILD_OPTION) $(PCIESC_SUPPORT_BUILD_OPTION) $(DSC_FTPM_ERROR_WR_BUILD_OPTIONS) $(DSC_TPM_BUILD_OPTIONS) $(DSC_BYTI_SECURE_BOOT_BUILD_OPTIONS) +!if $(PERFORMANCE_ENABLE) == TRUE + DEFINE PDB_BUILD_OPTION = /Zi +!endif + +!if $(SOURCE_DEBUG_ENABLE) == TRUE + MSFT:*_*_X64_GENFW_FLAGS = --keepexceptiontable + GCC:*_*_X64_GENFW_FLAGS = --keepexceptiontable + INTEL:*_*_X64_GENFW_FLAGS = --keepexceptiontable +!if $(TARGET) == DEBUG + DEFINE SOURCE_LEVEL_DEBUG_BUILD_OPTIONS = /Od /Oy- +!endif +!else + DEFINE SOURCE_LEVEL_DEBUG_BUILD_OPTIONS = + +!endif + +[BuildOptions.Common.EDK] + +# +# Define token for different Platform +# +!if $(ENBDT_PF_BUILD) == TRUE + DEFINE ENBDT_PF_ENABLE = /DENBDT_PF_ENABLE=1 +!else + DEFINE ENBDT_PF_ENABLE = /DENBDT_PF_ENABLE=0 +!endif + +!if $(PERFORMANCE_ENABLE) == TRUE + RELEASE_*_*_DLINK_FLAGS = /DEBUG +!endif + +!if $(S3_ENABLE) == TRUE + DEFINE DSC_S3_BUILD_OPTIONS = /DEFI_S3_RESUME +!else + DEFINE DSC_S3_BUILD_OPTIONS = +!endif + +!if $(ENBDT_S3_SUPPORT) == TRUE + DEFINE ENBDT_S3_SUPPORT_OPTIONS = /DNOCS_S3_SUPPORT +!else + DEFINE ENBDT_S3_SUPPORT_OPTIONS = +!endif + +!if $(X64_CONFIG) == TRUE + DEFINE X64_BUILD_ENABLE = /DX64_BUILD_ENABLE=1 +!else + DEFINE X64_BUILD_ENABLE = +!endif + + + DEFINE EDK_GLUE_LIB_DEBUG = + DEFINE DEBUG_BUILD_OPTIONS = /D EFI_DEBUG /D DEBUG_MODE=1 /GL- $(EDK_GLUE_LIB_DEBUG) /DEDKII_GLUE_DebugPrintErrorLevel=(EFI_D_ERROR) + DEFINE EDK_DSC_FEATURE_BUILD_OPTIONS = $(DSC_S3_BUILD_OPTIONS) $(DSC_ACPI_BUILD_OPTIONS) $(DSC_SEC_BUILD_OPTIONS) $(DSC_FTPM_BUILD_OPTIONS) $(DSC_FTPM_ERROR_WR_BUILD_OPTIONS) $(DSC_TPM_BUILD_OPTIONS) $(SOFTSDV_BUILD_OPTIONS) $(SIMICS_BUILD_OPTIONS) $(HYBRID_BUILD_OPTIONS) $(COMPACT_BUILD_OPTIONS) $(VP_BUILD_OPTIONS) $(QT_BUILD_OPTIONS) $(DSC_BYTI_SECURE_BOOT_BUILD_OPTIONS) /D$(PROJECT_SC_CHIPSET) + + DEFINE EDK_DSC_OTHER_BUILD_OPTIONS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) $(SV_BUILD_OPTIONS) $(INTEL_FASTBOOT_BUILD_OPTION) + DEFINE EDK_DSC_GLOBAL_BUILD_OPTIONS = $(ENBDT_PF_ENABLE) $(EDK_DSC_FEATURE_BUILD_OPTIONS) $(EDK_DSC_OTHER_BUILD_OPTIONS) /D EFI_SPECIFICATION_VERSION=0x00020000 /D PI_SPECIFICATION_VERSION=0x00000009 /D TIANO_RELEASE_VERSION=0x00080006 /D SUPPORT_DEPRECATED_PCI_CFG_PPI /D CSM_SMMENTRY_PORT8DATA8 /D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) /D MAX_VARIABLE_SIZE=0x2000 /D EFI_FIRMWARE_VENDOR="L/"INTEL/"" /D EFI_BUILD_VERSION="L/"EDKII/"" /DEFI_PEI_REPORT_STATUS_CODE_ON $(ENBDT_S3_SUPPORT_OPTIONS) + + *_*_IA32_ASM_FLAGS = /DEFI32 /D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h /DNOCS_S3_SUPPORT + DEBUG_*_IA32_CC_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_IA32_CC_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_IA32_VFRPP_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_IA32_VFRPP_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_IA32_APP_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_IA32_APP_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_IA32_PP_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_IA32_PP_FLAGS = /D EFI32 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + *_*_IA32_ASLPP_FLAGS = /D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) + *_*_IA32_ASLCC_FLAGS = /D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) + *_*_IA32_ASM16_FLAGS = /D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h + + *_*_X64_ASM_FLAGS = /DEFIX64 /D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h /DNOCS_S3_SUPPORT + DEBUG_*_X64_CC_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_X64_CC_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_X64_VFRPP_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_X64_VFRPP_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_X64_APP_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_X64_APP_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + DEBUG_*_X64_PP_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) $(DEBUG_BUILD_OPTIONS) + RELEASE_*_X64_PP_FLAGS = /D EFIX64 $(EDK_DSC_GLOBAL_BUILD_OPTIONS) + *_*_X64_ASLPP_FLAGS = /D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) + *_*_X64_ASLCC_FLAGS = /D EDKII_GLUE_PciExpressBaseAddress=0x$(PLATFORM_PCIEXPRESS_BASE) + *_*_X64_ASM16_FLAGS = /D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h + # *_*_*_BUILD_FLAGS = -s + *_*_*_VFR_FLAGS = -c + *_*_*_BUILD_FLAGS = -c + +[BuildOptions.Common.EDKII] + *_*_IA32_ASM_FLAGS = $(VP_BUILD_OPTIONS) /D EDKII_GLUE_PciExpressBaseAddress=$(PLATFORM_PCIEXPRESS_BASE)h /DNOCS_S3_SUPPORT + + *_*_IA32_CC_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_IA32_VFRPP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_IA32_APP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_IA32_PP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_IA32_ASLPP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + + *_*_X64_CC_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) $(SOURCE_LEVEL_DEBUG_BUILD_OPTIONS) + *_*_X64_VFRPP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_X64_APP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_X64_PP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + *_*_X64_ASLPP_FLAGS = $(EDK_EDKII_DSC_FEATURE_BUILD_OPTIONS) + + +[Components.X64] + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/SysFwUpdateCapsuleDxe.inf + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/I2cBus.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + } + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/I2cHost.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xF0000043 + } + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/I2cPortA0Pio.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x00000043 + } + + $(PLATFORM_BINARY_PACKAGE)/$(DXE_ARCHITECTURE)$(TARGET)/$(DXE_ARCHITECTURE)/I2cMmioDeviceDxe.inf { + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x00000043 + } diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/Boot.vfi b/Vlv2TbltDevicePkg/PlatformSetupDxe/Boot.vfi new file mode 100644 index 0000000000..c6c15239d4 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/Boot.vfi @@ -0,0 +1,77 @@ +// +// +// Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials are licensed and made available under +// the terms and conditions of the BSD License that accompanies this distribution. +// The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// +// +// Module Name: +// +// Boot.vfi +// +// Abstract: +// +// Driver Setup formset. +// +// Revision History: +// +// --*/ + + +form formid = BOOT_CONFIGURATION_FORM_ID, + + title = STRING_TOKEN(STR_BOOT_CONFIGURATION_TITLE); + + + oneof varid = Setup.FastBoot, + prompt = STRING_TOKEN(STR_FAST_BOOT_PROMPT), + help = STRING_TOKEN(STR_FAST_BOOT_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags= DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= MANUFACTURING | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.SecureBoot, + prompt = STRING_TOKEN(STR_SECURITY_BOOT_PROMPT), + help = STRING_TOKEN(STR_SECURITY_BOOT_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags= DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= RESET_REQUIRED; + endoneof; + + + oneof varid = Setup.QuietBoot, + prompt = STRING_TOKEN(STR_QUIETBOOT_PROMPT), + help = STRING_TOKEN(STR_QUIETBOOT_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags=0 | RESET_REQUIRED; + endoneof; + + + + oneof varid = Setup.LogBootTime, + prompt = STRING_TOKEN(STR_LOG_BOOT_TIME_PROMPT), + help = STRING_TOKEN(STR_LOG_BOOT_TIME_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = 0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + suppressif ideqval Setup.LogBootTime == 0x00; + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_LOG_BOOT_TIME_RECORD), + text = STRING_TOKEN(STR_LOG_BOOT_TIME_VALUE), + flags = 0, + key = 0; + endif; + +endform; + + + + diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/Configuration.h b/Vlv2TbltDevicePkg/PlatformSetupDxe/Configuration.h new file mode 100644 index 0000000000..b4e0e51f15 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/Configuration.h @@ -0,0 +1,61 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Configuration.h + +Abstract: + + Driver configuration include file + +Revision History: + ------------------------------------------------------------------------------ + Rev Date Name Description + ------------------------------------------------------------------------------ + + ------------------------------------------------------------------------------ +--*/ + +#ifndef _CONFIGURATION_H +#define _CONFIGURATION_H + +// +// System Setup Page. Do not have to be sequential but have to be unique +// +#define ROOT_FORM_ID 1 +#define ROOT_MAIN_FORM_ID 2 +#define CPU_CONFIGURATION_FORM_ID 3 +#define CPU_PWR_CONFIGURATION_FORM_ID 4 +#define BOOT_CONFIGURATION_FORM_ID 5 +#define IGD_FORM_ID 6 +#define SECURITY_CONFIGURATION_FORM_ID 7 +#define SOUTH_CLUSTER_FORM_ID 8 +#define DPTF_FORM_ID 9 +#define PLATFORM_INFORMATION_FORM_ID 10 +#define DRIVE_CONFIGURATION_ID 11 +#define SENSOR_CONFIGURATION_ID 12 +#define LPSS_CONFIGURATION_ID 13 +#define UNCORE_FORM_ID 14 +#define TPM_FORM_ID 15 +#define THERMAL_FORM_ID 16 +#define PASSWORD_SETTING_ID 17 +#define LAN_OPTIONS_FORM_ID 18 +#define AZALIA_OPTIONS_FORM_ID 19 +#define MISC_OPTIONS_FORM_ID 20 +#define USB_OPTIONS_FORM_ID 21 +#define PCIE_DEVICE_OPTIONS_FORM_ID 22 +#define SYSTEM_COMPONENT_FORM_ID 23 +#define DEBUG_CONFIGURATION_FORM_ID 24 +#endif // #ifndef _CONFIGURATION_H diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/DebugConfig.vfi b/Vlv2TbltDevicePkg/PlatformSetupDxe/DebugConfig.vfi new file mode 100644 index 0000000000..7065ffdf60 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/DebugConfig.vfi @@ -0,0 +1,123 @@ +// +// +// Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials are licensed and made available under +// the terms and conditions of the BSD License that accompanies this distribution. +// The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// +// +// +// Module Name: +// +// DebugConfiguration.vfi +// +// Abstract: +// +// Debug Configuration formset. +// + + +// --*/ + +form formid = DEBUG_CONFIGURATION_FORM_ID, + title = STRING_TOKEN(STR_DEBUG_CONFIGURATION_TITLE); + + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + subtitle text = STRING_TOKEN(STR_ACPIMEMDBG_STRING); + + //ACPI Memory Debug Switch + oneof varid = Setup.ACPIMemDbg, + prompt = STRING_TOKEN (STR_ACPIMEMDBG_SWTICH), + help = STRING_TOKEN (STR_ACPIMEMDBG_SWTICH_HELP), + option text = STRING_TOKEN (STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN (STR_DISABLE), value = 0, flags = RESET_REQUIRED; + endoneof; + + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + oneof varid = Setup.ExISupport, + prompt = STRING_TOKEN(STR_EXISUPPORT_PROMPT), + help = STRING_TOKEN(STR_EXISUPPORT_HELP), + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | RESET_REQUIRED; + endoneof; + subtitle text = STRING_TOKEN(STR_WITT_CONFIGURATION_TITLE); + + oneof varid = Setup.WittEnable, + prompt = STRING_TOKEN(STR_WITT_PROMPT), + help = STRING_TOKEN(STR_WITT_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + endoneof; + + oneof varid = Setup.UtsEnable, + prompt = STRING_TOKEN(STR_UTS_PROMPT), + help = STRING_TOKEN(STR_UTS_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + endoneof; + + // + //Lakemore Settings + // + subtitle text = STRING_TOKEN(STR_NULL_STRING); + subtitle text = STRING_TOKEN(STR_LM_INFORMATION_TITLE); + + grayoutif ideqval Setup.PunitBIOSConfig == 0x1; + oneof varid = Setup.LmMemSize, + prompt = STRING_TOKEN (STR_LM_MEMORY_PROMPT), + help = STRING_TOKEN (STR_LM_MEMORY_HELP), + option text = STRING_TOKEN (STR_LM_MEMORY_16MB), value = 16384, flags = RESET_REQUIRED; + option text = STRING_TOKEN (STR_LM_MEMORY_8MB), value = 8192, flags = RESET_REQUIRED; + option text = STRING_TOKEN (STR_LM_MEMORY_1MB), value = 1024, flags = RESET_REQUIRED; + option text = STRING_TOKEN (STR_LM_MEMORY_128KB), value = 128, flags = RESET_REQUIRED; + option text = STRING_TOKEN (STR_LM_MEMORY_0MB), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + oneof varid = Setup.PunitBIOSConfig, + prompt = STRING_TOKEN (STR_PUINT_BIOS_CONFIG_DISPLAY), + help = STRING_TOKEN (STR_PUINT_BIOS_CONFIG_DISPLAY_HELP), + option text = STRING_TOKEN (STR_PUINT_BIOS_PDM), value = 3, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN (STR_PUINT_BIOS_PERFORMANCE), value = 2, flags = RESET_REQUIRED; + option text = STRING_TOKEN (STR_PUINT_BIOS_POWERSAVE), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN (STR_PUINT_BIOS_RESERVED), value = 0, flags = RESET_REQUIRED; + endoneof; + + suppressif NOT ideqval Setup.PunitBIOSConfig == 0x3; + oneof varid = Setup.PDMConfig, + prompt = STRING_TOKEN (STR_PDM_OUTPUT_CONFIG_SWTICH), + help = STRING_TOKEN (STR_PDM_OUTPUT_CONFIG_SWTICH_HELP), + option text = STRING_TOKEN (STR_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN (STR_PDM_OUTPUT_MEM), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN (STR_PDM_OUTPUT_IO), value = 2, flags = RESET_REQUIRED; + endoneof; + endif; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + oneof varid = Setup.ENDBG2, + prompt = STRING_TOKEN (STR_ENABLE_DBG2), + help = STRING_TOKEN (STR_ENABLE_DBG2_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | RESET_REQUIRED; + endoneof; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + oneof varid = Setup.DisableCodec262, + prompt = STRING_TOKEN(STR_CODEC262_DISABLED_PROMPT), + help = STRING_TOKEN(STR_CODEC262_DISABLED_HELP), + option text = STRING_TOKEN(STR_YES), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_NO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + +endform; diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/FwVersionStrings.uni b/Vlv2TbltDevicePkg/PlatformSetupDxe/FwVersionStrings.uni new file mode 100644 index 0000000000000000000000000000000000000000..767388ce91bc761c980c2fc3b351b2251c605a45 GIT binary patch literal 4108 zcmd6p-ER_65XI-&#Q$MKU(}SM#-~P2sHK(I0-==ZQ^R*RDPUMy<)2r7=U$dw+R9=; zZ3uh6=FXgZ=FHvw`J-S3dumU37A&w2Hny)evx$W^uq&G~_slx>oc6W7fc4mi+PnNJGSid?i9qFQFgvpK`6J>Nf`b0AF9 z6thy$lw9mPeMwuMUD;0@*L$3QLWT-=*pHZLgT0H|mZR_C<%)m8Nz!ZBM=OD=hJvbg z%(G~xjLWbZz^mE@vt=}PPOs#+KDP>OiFtA2JtTQ3qv;YBXU=n#p0uoIj#hrW@unVl}4q1iyGG67Q>Y~>f3A^SLvw^K_6xCZDVXNq0Xg{$cU>$v!XqB;Lz#QA1gZc}S(jyxnaB?8Y!JRY)HdvO1)r}*9gXR7e(`3ioe4s;a;ps@0YYybgb6vze08R>}~c;klui0 zz}fDeuZiNC%z6az`BtNBqVW?LQY~-emyNPQ4vP!+A4Ycylj5)mt~%%Ob-6jG+30-a zfXI5w#0p)_ZKv)|8ozE{Pnt$a-7ot)+MBYDSZtG3HIV z^xDqGybh!1R7{PVTMGTRj3$viqpMj=tYe&yiN#OU^|l#Qma}v0Bd^2YGREz&w;slI zbf_ +// +// This program and the accompanying materials are licensed and made available under +// the terms and conditions of the BSD License that accompanies this distribution. +// The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// +// +// +// Module Name: +// +// Main.vfi +// +// Abstract: +// +// Driver Setup formset. +// +// Revision History: +// +// --*/ + +form formid = ROOT_MAIN_FORM_ID, + + title = STRING_TOKEN(STR_MAIN_TITLE); + + subtitle text = STRING_TOKEN(STR_BIOS_INFORMATION_TITLE); + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_IFWI_VERSION_STRING), + text = STRING_TOKEN(STR_IFWI_VERSION_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_BIOS_VERSION_STRING), + text = STRING_TOKEN(STR_BIOS_VERSION_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_BIOS_VENDOR_STRING), + text = STRING_TOKEN(STR_BIOS_VENDOR_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_CORE_VERSION_STRING), + text = STRING_TOKEN(STR_CORE_VERSION_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_BIOS_BUILD_TIME_STRING), + text = STRING_TOKEN(STR_BIOS_BUILD_TIME_VALUE), + flags = 0, + key = 0; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + subtitle text = STRING_TOKEN(STR_PROCESSOR_INFO_STRING); + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_PROCESSOR_VERSION_STRING), + text = STRING_TOKEN(STR_PROCESSOR_VERSION_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_PROCESSOR_SKU_STRING), + text = STRING_TOKEN(STR_PROCESSOR_SKU_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_PROCESSOR_SPEED_STRING), + text = STRING_TOKEN(STR_PROCESSOR_SPEED_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_PROCESSOR_ID_STRING), + text = STRING_TOKEN(STR_PROCESSOR_ID_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_PROCESSOR_MICROCODE_STRING), + text = STRING_TOKEN(STR_PROCESSOR_MICROCODE_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_PROCESSOR_CORE_STRING), + text = STRING_TOKEN(STR_PROCESSOR_CORE_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_EM64T_CAPABILITY_STRING), + text = STRING_TOKEN(STR_EM64T_CAPABILITY_VALUE), + flags = 0, + key = 0; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto PLATFORM_INFORMATION_FORM_ID, + prompt = STRING_TOKEN(STR_PLATFORM_INFORMATION_TITLE), + help = STRING_TOKEN(STR_PLATFORM_INFORMATION_HELP); + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + // + // Date and Time section + // + date year varid = Date.Year, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_DATE_PROMPT), + help = STRING_TOKEN(STR_DATE_YEAR_HELP), + minimum = 2003, + maximum = 2100, + step = 1, + default = 2003, + + month varid = Date.Month, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_DATE_PROMPT), + help = STRING_TOKEN(STR_DATE_MONTH_HELP), + minimum = 1, + maximum = 12, + step = 1, + default = 1, + + day varid = Date.Day, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_DATE_PROMPT), + help = STRING_TOKEN(STR_DATE_DAY_HELP), + minimum = 1, + maximum = 31, + step = 0x1, + default = 1, + + // If the day is 31 AND months is any of the following 2, 4, 6, 9, 11 + inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), + ideqval Date.Day == 31 + AND + ideqvallist Date.Month == 2 4 6 9 11 + endif + + // If the day is 30 AND month is 2 + inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), + ideqval Date.Day == 30 + AND + ideqval Date.Month == 2 + endif + + // If the day is 29 AND month is 2 AND it year is NOT a leapyear + inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), + ideqval Date.Day == 0x29 + AND + ideqval Date.Month == 2 + AND + NOT + ideqvallist Date.Year == 2004 2008 2012 2016 2020 2024 2028 2032 2036 2040 2044 2048 2052 2056 2060 2064 2068 2072 2076 2080 2084 2088 2092 2096 + endif + + enddate; + + time hour varid = Time.Hours, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_TIME_PROMPT), + help = STRING_TOKEN(STR_TIME_HOUR_HELP), + minimum = 0, + maximum = 23, + step = 1, + default = 0, + + minute varid = Time.Minutes, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_TIME_PROMPT), + help = STRING_TOKEN(STR_TIME_MINUTE_HELP), + minimum = 0, + maximum = 59, + step = 1, + default = 0, + + second varid = Time.Seconds, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_TIME_PROMPT), + help = STRING_TOKEN(STR_TIME_SECOND_HELP), + minimum = 0, + maximum = 59, + step = 1, + default = 0, + endtime; + +endform; + +form formid = PLATFORM_INFORMATION_FORM_ID, + + title = STRING_TOKEN(STR_PLATFORM_INFORMATION_TITLE); + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + subtitle text = STRING_TOKEN(STR_PLATFORM_FIRMWARE_STRING); + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_SOC_STRING), + text = STRING_TOKEN(STR_SOC_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_MRC_VERSION_STRING), + text = STRING_TOKEN(STR_MRC_VERSION_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_PUNIT_FW_STRING), + text = STRING_TOKEN(STR_PUNIT_FW_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_PMC_FW_STRING), + text = STRING_TOKEN(STR_PMC_FW_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_KSC_FW_STRING), + text = STRING_TOKEN(STR_KSC_FW_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_SEC_VERSION_STRING), + text = STRING_TOKEN(STR_SEC_VERSION_VALUE), + flags = 0, + key = 0; + + suppressif ideqval Setup.GOPEnable == 0; + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_GOP_STRING), + text = STRING_TOKEN(STR_GOP_VALUE), + flags = 0, + key = 0; + endif; + + suppressif ideqval Setup.GOPEnable == 1; + text + help = STRING_TOKEN(STR_CHIP_IGD_VBIOS_REV_HELP), + text = STRING_TOKEN(STR_CHIP_IGD_VBIOS_REV_NAME), + text = STRING_TOKEN(STR_CHIP_IGD_VBIOS_REV_VALUE), + flags = 0, + key = 0; + endif; + + text + help = STRING_TOKEN(STR_CPU_FLAVOR_HELP), + text = STRING_TOKEN(STR_CPU_FLAVOR_NAME), + text = STRING_TOKEN(STR_CPU_FLAVOR_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_BOARD_ID_HELP), + text = STRING_TOKEN(STR_BOARD_ID_NAME), + text = STRING_TOKEN(STR_BOARD_ID_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_FAB_ID_HELP), + text = STRING_TOKEN(STR_FAB_ID_STRING), + text = STRING_TOKEN(STR_FAB_ID_VALUE), + flags = 0, + key = 0; + + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + subtitle text = STRING_TOKEN(STR_MEMORY_INFORMATION_STRING); + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_TOTAL_MEMORY_SIZE_PROMPT), + text = STRING_TOKEN(STR_TOTAL_MEMORY_SIZE_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_SYSTEM_MEMORY_SPEED_STRING), + text = STRING_TOKEN(STR_SYSTEM_MEMORY_SPEED_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_PROCESSOR_L1_DATA_CACHE_STRING), + text = STRING_TOKEN(STR_PROCESSOR_L1_DATA_CACHE_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_PROCESSOR_L1_INSTR_CACHE_STRING), + text = STRING_TOKEN(STR_PROCESSOR_L1_INSTR_CACHE_VALUE), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_PROCESSOR_L2_CACHE_STRING), + text = STRING_TOKEN(STR_PROCESSOR_L2_CACHE_VALUE), + flags = 0, + key = 0; + +endform; + diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/PlatformSetupDxe.c b/Vlv2TbltDevicePkg/PlatformSetupDxe/PlatformSetupDxe.c new file mode 100644 index 0000000000..1490e2c030 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/PlatformSetupDxe.c @@ -0,0 +1,933 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + +**/ + +#include "PlatformSetupDxe.h" +#include "Guid/SetupVariable.h" + +#define EFI_CALLBACK_INFO_SIGNATURE SIGNATURE_32 ('C', 'l', 'b', 'k') +#define EFI_CALLBACK_INFO_FROM_THIS(a) CR (a, EFI_CALLBACK_INFO, ConfigAccess, EFI_CALLBACK_INFO_SIGNATURE) + +typedef struct { + UINTN Signature; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE RegisteredHandle; + SYSTEM_CONFIGURATION FakeNvData; + SYSTEM_CONFIGURATION BackupNvData; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; +} EFI_CALLBACK_INFO; + +#pragma pack(1) + +// +// HII specific Vendor Device Path definition. +// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +#pragma pack() + +// +// uni string and Vfr Binary data. +// +extern UINT8 VfrBin[]; +extern UINT8 PlatformSetupDxeStrings[]; + +EFI_HANDLE mImageHandle; + +// +// module global data +// +#define EFI_NORMAL_SETUP_GUID \ + { 0xec87d643, 0xeba4, 0x4bb5, 0xa1, 0xe5, 0x3f, 0x3e, 0x36, 0xb2, 0xd, 0xa9 } + +EFI_GUID mNormalSetupGuid = EFI_NORMAL_SETUP_GUID; + +EFI_GUID mSystemConfigGuid = SYSTEM_CONFIGURATION_GUID; +CHAR16 mVariableName[] = L"Setup"; +CHAR16 mSetupName[] = L"Setup"; +EFI_CALLBACK_INFO *mCallbackInfo; +BOOLEAN GlobalReset=FALSE; + +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + EFI_CALLER_ID_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ + +VOID +CheckSystemConfigLoad(SYSTEM_CONFIGURATION *SystemConfigPtr); + +VOID +CheckSystemConfigSave(SYSTEM_CONFIGURATION *SystemConfigPtr); + +VOID +ConfirmSecureBootTest(); + +VOID +LoadLpssDefaultValues ( + IN EFI_CALLBACK_INFO *Private + ) +{ + // + // Load LPSS and SCC defalut configurations for Android + // + Private->FakeNvData.LpsseMMCEnabled = FALSE; + Private->FakeNvData.LpssSdioEnabled = TRUE; + Private->FakeNvData.LpssSdcardEnabled = TRUE; + Private->FakeNvData.LpssSdCardSDR25Enabled = FALSE; + Private->FakeNvData.LpssSdCardDDR50Enabled = TRUE; + Private->FakeNvData.LpssMipiHsi = FALSE; + Private->FakeNvData.LpsseMMC45Enabled = TRUE; + Private->FakeNvData.LpsseMMC45DDR50Enabled = TRUE; + Private->FakeNvData.LpsseMMC45HS200Enabled = FALSE; + Private->FakeNvData.LpsseMMC45RetuneTimerValue = 8; + Private->FakeNvData.eMMCBootMode = 1; // Auto Detect + + Private->FakeNvData.GOPEnable = TRUE; + Private->FakeNvData.SecureBoot = TRUE; + Private->FakeNvData.UsbAutoMode = TRUE; + Private->FakeNvData.UsbXhciSupport = TRUE; + Private->FakeNvData.PchUsb30Mode = TRUE; + Private->FakeNvData.LegacyUSBBooting = FALSE; + Private->FakeNvData.PchUsb20 = FALSE; +} + + +EFI_STATUS +EFIAPI +SystemConfigExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + EFI_STATUS Status; + EFI_CALLBACK_INFO *Private; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + EFI_STRING ConfigRequestHdr; + EFI_STRING ConfigRequest; + BOOLEAN AllocatedRequest; + UINTN Size; + UINTN BufferSize; + VOID *SystemConfigPtr; + + + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Request; + if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mSystemConfigGuid, mVariableName)) { + return EFI_NOT_FOUND; + } + + ConfigRequestHdr = NULL; + ConfigRequest = NULL; + Size = 0; + AllocatedRequest = FALSE; + + Private = EFI_CALLBACK_INFO_FROM_THIS (This); + + SetupInfo(); + + HiiConfigRouting = Private->HiiConfigRouting; + ConfigRequest = Request; + if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { + // + // Request has no request element, construct full request string. + // Allocate and fill a buffer large enough to hold the template + // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator + // + ConfigRequestHdr = HiiConstructConfigHdr (&mSystemConfigGuid, mVariableName, Private->DriverHandle); + Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); + ConfigRequest = AllocateZeroPool (Size); + ASSERT (ConfigRequest != NULL); + AllocatedRequest = TRUE; + BufferSize = sizeof (SYSTEM_CONFIGURATION); + UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); + FreePool (ConfigRequestHdr); + } + SystemConfigPtr = GetVariable(mSetupName, &mNormalSetupGuid); + + + if (SystemConfigPtr == NULL) { + ZeroMem(&Private->FakeNvData, sizeof(SYSTEM_CONFIGURATION)); + ZeroMem(&Private->BackupNvData, sizeof(SYSTEM_CONFIGURATION)); + } else { + CheckSystemConfigLoad(SystemConfigPtr); + CopyMem(&Private->FakeNvData, SystemConfigPtr, sizeof(SYSTEM_CONFIGURATION)); + CopyMem(&Private->BackupNvData, SystemConfigPtr, sizeof(SYSTEM_CONFIGURATION)); + FreePool(SystemConfigPtr); + } + + // + // Convert buffer data to by helper function BlockToConfig() + // + Status = HiiConfigRouting->BlockToConfig ( + HiiConfigRouting, + ConfigRequest, + (UINT8 *) &Private->FakeNvData, + sizeof (SYSTEM_CONFIGURATION), + Results, + Progress + ); + + // + // Free the allocated config request string. + // + if (AllocatedRequest) { + FreePool (ConfigRequest); + ConfigRequest = NULL; + } + + // + // Set Progress string to the original request string. + // + if (Request == NULL) { + *Progress = NULL; + } else if (StrStr (Request, L"OFFSET") == NULL) { + *Progress = Request + StrLen (Request); + } + + return Status; +} + +/** + This function processes the results of changes in configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in format. + @param Progress A pointer to a string filled in with the offset of the most + recent '&' before the first failing name/value pair (or the + beginning of the string if the failure is in the first + name/value pair) or the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +SystemConfigRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + EFI_CALLBACK_INFO *Private; + SYSTEM_CONFIGURATION *FakeNvData; + + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Configuration; + + if (!HiiIsConfigHdrMatch (Configuration, &mSystemConfigGuid, mVariableName)) { + return EFI_NOT_FOUND; + } + + *Progress = Configuration + StrLen (Configuration); + Private = EFI_CALLBACK_INFO_FROM_THIS (This); + FakeNvData = &Private->FakeNvData; + if (!HiiGetBrowserData (&mSystemConfigGuid, mVariableName, sizeof (SYSTEM_CONFIGURATION), (UINT8 *) FakeNvData)) { + // + // FakeNvData can't be got from SetupBrowser, which doesn't need to be set. + // + return EFI_SUCCESS; + } + + if (Private->FakeNvData.ReservedO != Private->BackupNvData.ReservedO) { + Private->BackupNvData.ReservedO = Private->FakeNvData.ReservedO; + LoadLpssDefaultValues (Private); + + // + // Pass changed uncommitted data back to Form Browser + // + HiiSetBrowserData (&mSystemConfigGuid, mVariableName, sizeof (SYSTEM_CONFIGURATION), (UINT8 *) FakeNvData, NULL); + } + + gRT->SetVariable( + mSetupName, + &mNormalSetupGuid, + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(SYSTEM_CONFIGURATION), + &Private->FakeNvData + ); + + CheckSystemConfigSave(&Private->FakeNvData); + return EFI_SUCCESS; +} + +/** + This is the function that is called to provide results data to the driver. This data + consists of a unique key which is used to identify what data is either being passed back + or being asked for. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action A null-terminated Unicode string in format. + @param KeyValue A unique Goto OpCode callback value which record user's selection. + 0x100 <= KeyValue <0x500 : user select a controller item in the first page; + KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page + KeyValue == 0x1235 : user select 'Pci device filter' in first page + KeyValue == 0x1500 : user select 'order ... priority' item in second page + KeyValue == 0x1800 : user select 'commint changes' in third page + KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS Always returned. + +**/ +EFI_STATUS +EFIAPI +SystemConfigCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID KeyValue, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + EFI_CALLBACK_INFO *Private; + SYSTEM_CONFIGURATION *FakeNvData; + SYSTEM_CONFIGURATION *SetupData; + UINTN SizeOfNvStore; + EFI_INPUT_KEY Key; + CHAR16 *StringBuffer1; + CHAR16 *StringBuffer2; + CHAR16 *StringBuffer3; + EFI_STATUS Status; + UINTN DataSize; + UINT8 OsSelection; + + StringBuffer1 = AllocateZeroPool (200 * sizeof (CHAR16)); + ASSERT (StringBuffer1 != NULL); + StringBuffer2 = AllocateZeroPool (200 * sizeof (CHAR16)); + ASSERT (StringBuffer2 != NULL); + StringBuffer3 = AllocateZeroPool (200 * sizeof (CHAR16)); + ASSERT (StringBuffer3 != NULL); + + switch (Action) { + case EFI_BROWSER_ACTION_CHANGING: + { + if (KeyValue == 0x1235) { + StrCpy (StringBuffer1, L"Will you disable PTT ? "); + StrCpy (StringBuffer2, L"Enter (YES) / Esc (NO)"); + + // + // Popup a menu to notice user + // + do { + CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL); + } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN)); + + // + // If the user hits the YES Response key, + // + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + + } + } else if (KeyValue == 0x1236) { + StrCpy (StringBuffer1, L"Will you revoke trust ? "); + StrCpy (StringBuffer2, L"Enter (YES) / Esc (NO)"); + + // + // Popup a menu to notice user + // + do { + CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL); + } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN)); + + // + // If the user hits the YES Response key, + // + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + + } + } else if (KeyValue == 0x1239) { + if (Value->u8 == 0x00) { + StrCpy (StringBuffer1, L"WARNING: SOC may be damaged due to high temperature"); + StrCpy (StringBuffer2, L"when DPTF is disabled and IGD turbo is enabled."); + StrCpy (StringBuffer3, L"Press Enter/ESC to continue..."); + + // + // Popup a menu to notice user + // + do { + CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, StringBuffer3, NULL); + } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN)); + } + } else if (KeyValue == 0x1240) { // secure erase feature of eMMC + // + // Popup a menu to notice user + // + StrCpy (StringBuffer1, L"WARNING: All your data on the eMMC will be lost"); + StrCpy (StringBuffer2, L"Do you really want to enable secure erase on eMMC?"); + StrCpy (StringBuffer3, L" Enter (YES) / Esc (NO) "); + + do { + CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, StringBuffer3,NULL); + } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN)); + + // + // If the user hits the ESC Response key, + // + if (Key.ScanCode == SCAN_ESC) { + Private = EFI_CALLBACK_INFO_FROM_THIS (This); + FakeNvData = &Private->FakeNvData; + + Status = HiiGetBrowserData ( + &mSystemConfigGuid, + mVariableName, + sizeof (SYSTEM_CONFIGURATION), + (UINT8 *) FakeNvData + ); + if (!EFI_ERROR (Status)) { + FakeNvData->SecureErase = 0; + HiiSetBrowserData ( + &mSystemConfigGuid, + mVariableName, + sizeof (SYSTEM_CONFIGURATION), + (UINT8 *) FakeNvData, + NULL + ); + } + break; + } + + // + // If the user hits the YES Response key + // + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + // + // Save change + // + Private = EFI_CALLBACK_INFO_FROM_THIS (This); + FakeNvData = &Private->FakeNvData; + + Status = HiiGetBrowserData ( + &mSystemConfigGuid, + mVariableName, + sizeof (SYSTEM_CONFIGURATION), + (UINT8 *) FakeNvData + ); + if (!EFI_ERROR (Status)) { + Status = gRT->SetVariable ( + L"Setup", + &mNormalSetupGuid, + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(SYSTEM_CONFIGURATION), + &Private->FakeNvData + ); + } + + // + // Reset system + // + gRT->ResetSystem( + EfiResetCold, + EFI_SUCCESS, + 0, + NULL + ); + + } + + + } + else if (KeyValue == 0xF001) { + // + // Popup a menu to notice user + // + StrCpy (StringBuffer1, L"Do you want to Commit Changes and Exit?"); + StrCpy (StringBuffer2, L" Enter (YES) / Esc (NO) "); + + do { + CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL); + } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN)); + + // + // If the user hits the YES Response key + // + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + // + // Save change + // + Private = EFI_CALLBACK_INFO_FROM_THIS (This); + FakeNvData = &Private->FakeNvData; + + Status = HiiGetBrowserData ( + &mSystemConfigGuid, + mVariableName, + sizeof (SYSTEM_CONFIGURATION), + (UINT8 *) FakeNvData + ); + if (!EFI_ERROR (Status)) { + Status = gRT->SetVariable ( + L"Setup", + &mNormalSetupGuid, + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(SYSTEM_CONFIGURATION), + &Private->FakeNvData + ); + } + + // + // Update Secure Boot configuration changes + // + CheckSystemConfigSave(FakeNvData); + + // + // Reset system + // + if (GlobalReset == TRUE) { + // + // Issue full reset + // + IoWrite8 ( + (UINTN) 0XCF9, + (UINT8) 0x02 + ); + + IoWrite8 ( + (UINTN) 0xCF9, + (UINT8) 0x0E + ); + } else { + gRT->ResetSystem( + EfiResetCold, + EFI_SUCCESS, + 0, + NULL + ); + } + } + } else if (KeyValue == 0xF002) { + // + // Popup a menu to notice user + // + StrCpy (StringBuffer1, L"Do you want to Discard Changes and Exit?"); + StrCpy (StringBuffer2, L" Enter (YES) / Esc (NO) "); + + do { + CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL); + } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN)); + + // + // If the user hits the YES Response key + // + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + // + // Reset system + // + gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); + } + } else if (KeyValue == 0xF003) { + // + // Popup a menu to notice user + // + StrCpy (StringBuffer1, L"Do you want to load setup defaults and Exit?"); + StrCpy (StringBuffer2, L" Enter (YES) / Esc (NO) "); + + do { + CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL); + } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN)); + + // + // If the user hits the YES Response key + // + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + // + // Load default + // + FakeNvData = AllocateZeroPool (sizeof(SYSTEM_CONFIGURATION)); + + if (FakeNvData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SizeOfNvStore = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + L"SetupDefault", + &mNormalSetupGuid, + NULL, + &SizeOfNvStore, + FakeNvData + ); + if (!EFI_ERROR (Status)) { + if(SizeOfNvStore >= sizeof(SYSTEM_CONFIGURATION)) { + Status = gRT->SetVariable ( + L"Setup", + &mNormalSetupGuid, + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(SYSTEM_CONFIGURATION), + FakeNvData + ); + } + } + + FreePool (FakeNvData); + + DataSize = sizeof(OsSelection); + Status = gRT->GetVariable( + L"OsSelection", + &gOsSelectionVariableGuid, + NULL, + &DataSize, + &OsSelection + ); + + if (EFI_ERROR(Status) || (OsSelection != FakeNvData->ReservedO)) { + OsSelection = FakeNvData->ReservedO; + Status = gRT->SetVariable ( + L"OsSelection", + &gOsSelectionVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof(OsSelection), + &OsSelection + ); + } + + // + // Reset system + // + gRT->ResetSystem( + EfiResetCold, + EFI_SUCCESS, + 0, + NULL + ); + } + } else if ((KeyValue == 0x123A) || (KeyValue == 0x123B) || (KeyValue == 0x123C)) { + StrCpy (StringBuffer1, L"WARNING: Enable or disable USB Controllers will "); + StrCpy (StringBuffer2, L"make global reset to restart system."); + StrCpy (StringBuffer3, L"Press Enter/ESC to continue..."); + // + // Popup a menu to notice user + // + do { + CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, StringBuffer3, NULL); + } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN)); + + FakeNvData = AllocateZeroPool (sizeof(SYSTEM_CONFIGURATION)); + Status = HiiGetBrowserData ( + &mSystemConfigGuid, + mVariableName, + sizeof (SYSTEM_CONFIGURATION), + (UINT8 *) FakeNvData + ); + // + // Get variable data + // + SizeOfNvStore = sizeof(SYSTEM_CONFIGURATION); + SetupData = AllocateZeroPool (sizeof(SYSTEM_CONFIGURATION)); + Status = gRT->GetVariable( + L"Setup", + &mNormalSetupGuid, + NULL, + &SizeOfNvStore, + SetupData + ); + if ((SetupData->UsbAutoMode != FakeNvData->UsbAutoMode) || + (SetupData->UsbXhciSupport != FakeNvData->UsbXhciSupport) || + (SetupData->PchUsb20 != FakeNvData->PchUsb20)) { + GlobalReset = TRUE; + } else { + GlobalReset = FALSE; + } + + } + } + break; + + default: + break; + } + + FreePool (StringBuffer1); + FreePool (StringBuffer2); + FreePool (StringBuffer3); + + // + // Workaround for Load Default for "DPTF Enable" + // + if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) { + if (KeyValue == 0x1239) { + return EFI_NOT_FOUND; + } + } + + if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) { + // + // Do nothing for UEFI OPEN/CLOSE Action + // + return EFI_SUCCESS; + } + + Private = EFI_CALLBACK_INFO_FROM_THIS (This); + FakeNvData = &Private->FakeNvData; + if (!HiiGetBrowserData (&mSystemConfigGuid, mVariableName, sizeof (SYSTEM_CONFIGURATION), (UINT8 *) FakeNvData)) { + return EFI_NOT_FOUND; + } + + if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) && (Private->FakeNvData.ReservedO != Private->BackupNvData.ReservedO)) { + Private->BackupNvData.ReservedO = Private->FakeNvData.ReservedO; + LoadLpssDefaultValues (Private); + } + + // + // When user selected the secure erase, set it to disable + // + if((KeyValue == 0x1240) && (Action == EFI_BROWSER_ACTION_CHANGED)) { + FakeNvData->SecureErase = 0; + } + + if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_CHANGED)) { + // + // If function 0 is disabled, function 1 ~ 7 also required to be disabled. + // + if (Private->FakeNvData.LpssDma0Enabled == 0) { + Private->FakeNvData.LpssHsuart0Enabled = 0; + Private->FakeNvData.LpssHsuart1Enabled = 0; + Private->FakeNvData.LpssPwm0Enabled = 0; + Private->FakeNvData.LpssPwm1Enabled = 0; + Private->FakeNvData.LpssSpiEnabled = 0; + } + + + // + // If function 0 is disabled, function 1 ~ 7 also required to be disabled. + // + if (Private->FakeNvData.LpssDma1Enabled == 0) { + Private->FakeNvData.LpssI2C0Enabled = 0; + Private->FakeNvData.LpssI2C1Enabled = 0; + Private->FakeNvData.LpssI2C2Enabled = 0; + Private->FakeNvData.LpssI2C3Enabled = 0; + Private->FakeNvData.LpssI2C4Enabled = 0; + Private->FakeNvData.LpssI2C5Enabled = 0; + Private->FakeNvData.LpssI2C6Enabled = 0; + } + } + + + // + // Pass changed uncommitted data back to Form Browser + // + HiiSetBrowserData (&mSystemConfigGuid, mVariableName, sizeof (SYSTEM_CONFIGURATION), (UINT8 *) FakeNvData, NULL); + + return EFI_SUCCESS; +} + + +/** + The driver Entry Point. The funciton will export a disk device class formset and + its callback function to hii database. + + @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 +PlatformSetupDxeInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; + + mImageHandle = ImageHandle; + + // + // There should only be one Form Configuration protocol + // + Status = gBS->LocateProtocol ( + &gEfiFormBrowser2ProtocolGuid, + NULL, + (VOID **) &FormBrowser2 + ); + if (EFI_ERROR (Status)) { + return Status; + } + + mCallbackInfo = AllocateZeroPool (sizeof (EFI_CALLBACK_INFO)); + if (mCallbackInfo == NULL) { + return EFI_BAD_BUFFER_SIZE; + } + + mCallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE; + mCallbackInfo->ConfigAccess.ExtractConfig = SystemConfigExtractConfig; + mCallbackInfo->ConfigAccess.RouteConfig = SystemConfigRouteConfig; + mCallbackInfo->ConfigAccess.Callback = SystemConfigCallback; + + // + // Install Device Path Protocol and Config Access protocol to driver handle + // Install Platform Driver Override Protocol to driver handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mCallbackInfo->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mCallbackInfo->ConfigAccess, + NULL + ); + if (EFI_ERROR (Status)) { + goto Finish; + } + + // + // Publish our HII data + // + mCallbackInfo->RegisteredHandle = HiiAddPackages ( + &mSystemConfigGuid, + mCallbackInfo->DriverHandle, + VfrBin, + PlatformSetupDxeStrings, + NULL + ); + if (mCallbackInfo->RegisteredHandle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Finish; + } + + mHiiHandle = mCallbackInfo->RegisteredHandle; + + // + // Locate ConfigRouting protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiConfigRoutingProtocolGuid, + NULL, + (VOID **) &mCallbackInfo->HiiConfigRouting + ); + if (EFI_ERROR (Status)) { + goto Finish; + } + + // + // Clear all the globle variable + // + return EFI_SUCCESS; + +Finish: + if (mCallbackInfo->DriverHandle != NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + mCallbackInfo->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mCallbackInfo->ConfigAccess, + NULL + ); + } + + if (mCallbackInfo->RegisteredHandle != NULL) { + HiiRemovePackages (mCallbackInfo->RegisteredHandle); + } + + if (mCallbackInfo != NULL) { + FreePool (mCallbackInfo); + } + + return Status; +} + +/** + Unload its installed protocol. + + @param[in] ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. +**/ +EFI_STATUS +EFIAPI +PlatformSetupDxeUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + if (mCallbackInfo != NULL) { + if (mCallbackInfo->DriverHandle != NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + mCallbackInfo->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mCallbackInfo->ConfigAccess, + NULL + ); + } + + if (mCallbackInfo->RegisteredHandle != NULL) { + HiiRemovePackages (mCallbackInfo->RegisteredHandle); + } + + FreePool (mCallbackInfo); + } + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/PlatformSetupDxe.h b/Vlv2TbltDevicePkg/PlatformSetupDxe/PlatformSetupDxe.h new file mode 100644 index 0000000000..ebe5547902 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/PlatformSetupDxe.h @@ -0,0 +1,102 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +**/ + +#ifndef _PLAT_OVER_MNGR_H_ +#define _PLAT_OVER_MNGR_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Guid/SetupVariable.h" +#include "Guid/OsSelection.h" + +#include +#include +#include +#include +extern EFI_HII_HANDLE mHiiHandle; + +UINT32 +ConvertBase10ToRaw ( + IN EFI_EXP_BASE10_DATA *Data); + +UINT32 +ConvertBase2ToRaw ( + IN EFI_EXP_BASE2_DATA *Data); + +EFI_STATUS +GetStringFromToken ( + IN EFI_GUID *ProducerGuid, + IN STRING_REF Token, + OUT CHAR16 **String + ); + +VOID +SwapEntries ( + IN CHAR8 *Data + ); + +VOID +AsciiToUnicode ( + IN CHAR8 *AsciiString, + IN CHAR16 *UnicodeString + ); + +VOID +EFIAPI +SetupInfo ( + ); + + +extern EFI_HANDLE mImageHandle; + +#endif diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/PlatformSetupDxe.inf b/Vlv2TbltDevicePkg/PlatformSetupDxe/PlatformSetupDxe.inf new file mode 100644 index 0000000000..9cd774b427 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/PlatformSetupDxe.inf @@ -0,0 +1,145 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# This driver produces UEFI PLATFORM_DRIVER_OVERRIDE_PROTOCOL if this protocol doesn't exist. +# It doesn't install again if this protocol exists. +# It only implements one interface GetDriver of PLATFORM_DRIVER_OVERRIDE_PROTOCOL protocol +# and doesn't support other two interfaces GetDriverPath, DriverLoaded. +# +# This driver also offers an UI interface in device manager to let user configure +# platform override protocol to override the default algorithm for matching +# drivers to controllers. +# +# The main flow: +# 1. It dynamicly locate all controller device path. +# 2. It dynamicly locate all drivers which support binding protocol. +# 3. It export and dynamicly update two menu to let user select the +# mapping between drivers to controllers. +# 4. It save all the mapping info in NV variables for the following boot, +# which will be consumed by GetDriver API of the produced the platform override protocol. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformSetupDxe + FILE_GUID = C1A69A12-8653-4fde-A215-48FCD95288C3 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PlatformSetupDxeInit + UNLOAD_IMAGE = PlatformSetupDxeUnload + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + VfrStrings.uni + FwVersionStrings.uni + Vfr.vfr + Main.vfi + Boot.vfi + PlatformSetupDxe.c + SetupInfoRecords.c + PlatformSetupDxe.h + Security.vfi + SouthClusterConfig.vfi + Thermal.vfi + SetupFunctions.c + UnCore.vfi + SystemComponent.vfi + DebugConfig.vfi + UqiList.uni + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec #for PchAccess.h + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + UefiLib + UefiDriverEntryPoint + UefiBootServicesTableLib + HiiLib + BaseMemoryLib + MemoryAllocationLib + DevicePathLib + DxeServicesTableLib + UefiRuntimeServicesTableLib + PrintLib + BiosIdLib + CpuIA32Lib + IoLib + +[Guids] + ## This GUID C Name is not required for build since it is from UefiLib and not directly used by this module source. + ## gEfiGlobalVariableGuid ## SOMETIMES_CONSUMED ## Variable:L"PlatformLang" this variable specifies the platform supported language string (RFC 4646 format) + ## gEfiGlobalVariableGuid ## SOMETIMES_CONSUMED ## Variable:L"Lang" this variable specifies the platform supported language string (ISO 639-2 format) + ## + # There could be more than one variables, from PlatDriOver, PlatDriOver1, PlatDriOver2,... + # + # gEfiCallerIdGuid ## Private ## Variable:L"PlatDriOver" + gEfiIfrTianoGuid ## CONSUMES ## Guid + gEfiProcessorSubClassGuid + gEfiMiscSubClassGuid + gEfiCacheSubClassGuid + gEfiMemorySubClassGuid + gEfiPlatformInfoGuid + gEfiNormalSetupGuid + gEfiSecureBootEnableDisableGuid + gOsSelectionVariableGuid + gEfiGlobalVariableGuid + +[Protocols] + gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMED (Get Driver Name if ComponentName2Protocol exists) + gEfiComponentNameProtocolGuid ## SOMETIMES_CONSUMED (Get Driver Name if ComponentNameProtocol exists and ComponentName2Protocol doesn't exist) + gEfiFirmwareVolume2ProtocolGuid ## SOMETIMES_CONSUMED (Get Driver Name from EFI UI section if ComponentName2Protocol and ComponentNameProtocol don't exist) + gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMED (Find the PCI device if PciIo protocol is installed) + gEfiPciRootBridgeIoProtocolGuid + gEfiBusSpecificDriverOverrideProtocolGuid ## SOMETIMES_CONSUMED (Check whether the PCI device contains one or more efi drivers in its option rom by this protocol) + + gEfiDriverBindingProtocolGuid ## SOMETIMES_CONSUMED + gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMED + gEfiLoadedImageDevicePathProtocolGuid ## SOMETIMES_CONSUMED (Show the drivers in the second page that support DriverBindingProtocol, LoadedImageProtocol and LoadedImageDevicePathProtocol) + gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMED (Show the controller device in the first page that support DevicePathProtocol) + + gEfiFormBrowser2ProtocolGuid ## CONSUMED + gEfiHiiConfigRoutingProtocolGuid ## CONSUMED + gEfiHiiConfigAccessProtocolGuid ## PRODUCED + gEfiDevicePathToTextProtocolGuid ## CONSUMED + + gEfiDataHubProtocolGuid + gEfiLegacyBiosProtocolGuid + gEfiSimpleNetworkProtocolGuid + + gEfiDiskInfoProtocolGuid ## CONSUMED + gEfiMpServiceProtocolGuid + gDxePchPlatformPolicyProtocolGuid + gEfiCpuIo2ProtocolGuid + gEfiTdtOperationProtocolGuid + gEfiSmbiosProtocolGuid ## PROTOCOL CONSUMES + +[Pcd.common] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + +[Depex] + gEfiFormBrowser2ProtocolGuid AND gEfiHiiConfigRoutingProtocolGuid diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/Security.vfi b/Vlv2TbltDevicePkg/PlatformSetupDxe/Security.vfi new file mode 100644 index 0000000000..f4922ff0b6 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/Security.vfi @@ -0,0 +1,96 @@ +// +// +// Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials are licensed and made available under +// the terms and conditions of the BSD License that accompanies this distribution. +// The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// +// +// +// Module Name: +// +// Security.vfi +// +// Abstract: +// +// Driver Setup formset. +// +// --*/ + +// +// Security Configuration Form +// + + +form formid = SECURITY_CONFIGURATION_FORM_ID, + title = STRING_TOKEN(STR_SECURITY_CONFIGURATION_TITLE); + + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + // + //TPM related + // + subtitle text = STRING_TOKEN(STR_TPM_CONFIGURATION_PROMPT); + oneof varid = Setup.ETpm, + prompt = STRING_TOKEN(STR_TPM_PROMPT), + help = STRING_TOKEN(STR_TPM_HELP), + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value= 0, flags= RESET_REQUIRED; + endoneof; + + oneof varid = Setup.MeasuredBootEnable, + prompt = STRING_TOKEN(STR_MEASURED_BOOT_ENABLE_PROMPT), + help = STRING_TOKEN(STR_MEASURED_BOOT_ENABLE_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + subtitle text = STRING_TOKEN(STR_PASSWORD_CONFIGURATION_SUBTITLE); + + password varid = Setup.AdminPassword, + prompt = STRING_TOKEN(STR_ADMIN_PASSWORD), + help = STRING_TOKEN(STR_ADMIN_PASSWORD_HELP), + flags = 0, + minsize = 0, + maxsize = PASSWORD_MAX_SIZE, + encoding = 1, + endpassword; + + password varid = Setup.UserPassword, + prompt = STRING_TOKEN(STR_USER_PASSWORD), + help = STRING_TOKEN(STR_USER_PASSWORD_HELP), + flags = 0, + minsize = 0, + maxsize = PASSWORD_MAX_SIZE, + encoding = 1, + endpassword; +suppressif TRUE; + password varid = Setup.AdminPassword, + prompt = STRING_TOKEN(STR_CHANGE_ADMIN_PASSWORD), + help = STRING_TOKEN(STR_CHANGE_ADMIN_PASSWORD_HELP), + flags = 0, + minsize = 0, + maxsize = PASSWORD_MAX_SIZE, + encoding = 1, + endpassword; + + password varid = Setup.UserPassword, + prompt = STRING_TOKEN(STR_CHANGE_USER_PASSWORD), + help = STRING_TOKEN(STR_CHANGE_USER_PASSWORD_HELP), + flags = 0, + minsize = 0, + maxsize = PASSWORD_MAX_SIZE, + encoding = 1, + endpassword; +endif; + +endform; + diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/SetupFunctions.c b/Vlv2TbltDevicePkg/PlatformSetupDxe/SetupFunctions.c new file mode 100644 index 0000000000..9d8d0a0e16 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/SetupFunctions.c @@ -0,0 +1,90 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + SetupFunctions.c + +Abstract: + +Revision History + +--*/ + +#include "PlatformSetupDxe.h" + +VOID +AsciiToUnicode ( + IN CHAR8 *AsciiString, + IN CHAR16 *UnicodeString + ) +{ + UINT8 Index; + + Index = 0; + while (AsciiString[Index] != 0) { + UnicodeString[Index] = (CHAR16)AsciiString[Index]; + Index++; + } +} + +VOID +SwapEntries ( + IN CHAR8 *Data + ) +{ + UINT16 Index; + CHAR8 Temp8; + + Index = 0; + while (Data[Index] != 0 && Data[Index+1] != 0) { + Temp8 = Data[Index]; + Data[Index] = Data[Index+1]; + Data[Index+1] = Temp8; + Index +=2; + } + + return; +} + +UINT32 +ConvertBase10ToRaw ( + IN EFI_EXP_BASE10_DATA *Data) +{ + UINTN Index; + UINT32 RawData; + + RawData = Data->Value; + for (Index = 0; Index < (UINTN) Data->Exponent; Index++) { + RawData *= 10; + } + + return RawData; +} + +UINT32 +ConvertBase2ToRaw ( + IN EFI_EXP_BASE2_DATA *Data) +{ + UINTN Index; + UINT32 RawData; + + RawData = Data->Value; + for (Index = 0; Index < (UINTN) Data->Exponent; Index++) { + RawData <<= 1; + } + + return RawData; +} + diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/SetupInfoRecords.c b/Vlv2TbltDevicePkg/PlatformSetupDxe/SetupInfoRecords.c new file mode 100644 index 0000000000..99684e72d7 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/SetupInfoRecords.c @@ -0,0 +1,1865 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + SetupInfoRecords.c + +Abstract: + + This is the filter driver to retrieve data hub entries. + +Revision History: +--*/ + +#include "PlatformSetupDxe.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Valleyview.h" +#include "VlvAccess.h" +#include "PchAccess.h" +#include "SetupMode.h" +#include "PchCommonDefinitions.h" +#include + + +typedef struct { + UINT8 ID; + CHAR8 String[16]; +} VLV_REV; + +typedef struct { + UINT8 RevId; + CHAR8 String[16]; +} SB_REV; + +// +// Silicon Steppings +// +SB_REV SBRevisionTable[] = { + {V_PCH_LPC_RID_0, "(A0 Stepping)"}, + {V_PCH_LPC_RID_1, "(A0 Stepping)"}, + {V_PCH_LPC_RID_2, "(A1 Stepping)"}, + {V_PCH_LPC_RID_3, "(A1 Stepping)"}, + {V_PCH_LPC_RID_4, "(B0 Stepping)"}, + {V_PCH_LPC_RID_5, "(B0 Stepping)"}, + {V_PCH_LPC_RID_6, "(B1 Stepping)"}, + {V_PCH_LPC_RID_7, "(B1 Stepping)"}, + {V_PCH_LPC_RID_8, "(B2 Stepping)"}, + {V_PCH_LPC_RID_9, "(B2 Stepping)"}, + {V_PCH_LPC_RID_A, "(B3 Stepping)"}, + {V_PCH_LPC_RID_B, "(B3 Stepping)"}, + {V_PCH_LPC_RID_C, "(C0 Stepping)"}, + {V_PCH_LPC_RID_D, "(C0 Stepping)"} +}; + +#define LEFT_JUSTIFY 0x01 +#define PREFIX_SIGN 0x02 +#define PREFIX_BLANK 0x04 +#define COMMA_TYPE 0x08 +#define LONG_TYPE 0x10 +#define PREFIX_ZERO 0x20 + +#define ICH_REG_REV 0x08 +#define MSR_IA32_PLATFORM_ID 0x17 + + +BOOLEAN mSetupInfoDone = FALSE; +UINT8 mUseProductKey = 0; +EFI_EXP_BASE10_DATA mProcessorFrequency; +EFI_EXP_BASE10_DATA mProcessorFsbFrequency; + +EFI_GUID mProcessorProducerGuid; +EFI_HII_HANDLE mHiiHandle; +EFI_PLATFORM_CPU_INFO mPlatformCpuInfo; +SYSTEM_CONFIGURATION mSystemConfiguration; +EFI_PLATFORM_INFO_HOB *mPlatformInfo; + + +#define memset SetMem + +UINT16 mMemorySpeed = 0xffff; +EFI_PHYSICAL_ADDRESS mMemorySizeChannelASlot0 = 0; +UINT16 mMemorySpeedChannelASlot0 = 0xffff; +EFI_PHYSICAL_ADDRESS mMemorySizeChannelASlot1 = 0; +UINT16 mMemorySpeedChannelASlot1 = 0xffff; +EFI_PHYSICAL_ADDRESS mMemorySizeChannelBSlot0 = 0; +UINT16 mMemorySpeedChannelBSlot0 = 0xffff; +EFI_PHYSICAL_ADDRESS mMemorySizeChannelBSlot1 = 0; +UINT16 mMemorySpeedChannelBSlot1 = 0xffff; +EFI_PHYSICAL_ADDRESS mMemorySizeChannelCSlot0 = 0; +UINT16 mMemorySpeedChannelCSlot0 = 0xffff; +EFI_PHYSICAL_ADDRESS mMemorySizeChannelCSlot1 = 0; +UINT16 mMemorySpeedChannelCSlot1 = 0xffff; +UINTN mMemoryMode = 0xff; + +#define CHARACTER_NUMBER_FOR_VALUE 30 + typedef struct { + EFI_STRING_TOKEN MemoryDeviceLocator; + EFI_STRING_TOKEN MemoryBankLocator; + EFI_STRING_TOKEN MemoryManufacturer; + EFI_STRING_TOKEN MemorySerialNumber; + EFI_STRING_TOKEN MemoryAssetTag; + EFI_STRING_TOKEN MemoryPartNumber; + EFI_INTER_LINK_DATA MemoryArrayLink; + EFI_INTER_LINK_DATA MemorySubArrayLink; + UINT16 MemoryTotalWidth; + UINT16 MemoryDataWidth; + UINT64 MemoryDeviceSize; + EFI_MEMORY_FORM_FACTOR MemoryFormFactor; + UINT8 MemoryDeviceSet; + EFI_MEMORY_ARRAY_TYPE MemoryType; + EFI_MEMORY_TYPE_DETAIL MemoryTypeDetail; + UINT16 MemorySpeed; + EFI_MEMORY_STATE MemoryState; +} EFI_MEMORY_ARRAY_LINK; + + +typedef struct { + EFI_PHYSICAL_ADDRESS MemoryArrayStartAddress; + EFI_PHYSICAL_ADDRESS MemoryArrayEndAddress; + EFI_INTER_LINK_DATA PhysicalMemoryArrayLink; + UINT16 MemoryArrayPartitionWidth; +} EFI_MEMORY_ARRAY_START_ADDRESS; + + +typedef enum { + PCH_SATA_MODE_IDE = 0, + PCH_SATA_MODE_AHCI, + PCH_SATA_MODE_RAID, + PCH_SATA_MODE_MAX +} PCH_SATA_MODE; + +/** + Acquire the string associated with the Index from smbios structure and return it. + The caller is responsible for free the string buffer. + + @param OptionalStrStart The start position to search the string + @param Index The index of the string to extract + @param String The string that is extracted + + @retval EFI_SUCCESS The function returns EFI_SUCCESS always. + +**/ +EFI_STATUS +GetOptionalStringByIndex ( + IN CHAR8 *OptionalStrStart, + IN UINT8 Index, + OUT CHAR16 **String + ) +{ + UINTN StrSize; + + if (Index == 0) { + *String = AllocateZeroPool (sizeof (CHAR16)); + return EFI_SUCCESS; + } + + StrSize = 0; + do { + Index--; + OptionalStrStart += StrSize; + StrSize = AsciiStrSize (OptionalStrStart); + } while (OptionalStrStart[StrSize] != 0 && Index != 0); + + if ((Index != 0) || (StrSize == 1)) { + // + // Meet the end of strings set but Index is non-zero, or + // Find an empty string + // + return EFI_NOT_FOUND; + } else { + *String = AllocatePool (StrSize * sizeof (CHAR16)); + AsciiStrToUnicodeStr (OptionalStrStart, *String); + } + + return EFI_SUCCESS; +} + +/** + VSPrint worker function that prints a Value as a decimal number in Buffer + + @param Buffer Location to place ascii decimal number string of Value. + @param Value Decimal value to convert to a string in Buffer. + @param Flags Flags to use in printing decimal string, see file header for details. + @param Width Width of hex value. + + Number of characters printed. + +**/ +UINTN +EfiValueToString ( + IN OUT CHAR16 *Buffer, + IN INT64 Value, + IN UINTN Flags, + IN UINTN Width + ) +{ + CHAR16 TempBuffer[CHARACTER_NUMBER_FOR_VALUE]; + CHAR16 *TempStr; + CHAR16 *BufferPtr; + UINTN Count; + UINTN ValueCharNum; + UINTN Remainder; + CHAR16 Prefix; + UINTN Index; + BOOLEAN ValueIsNegative; + UINT64 TempValue; + + TempStr = TempBuffer; + BufferPtr = Buffer; + Count = 0; + ValueCharNum = 0; + ValueIsNegative = FALSE; + + if (Width > CHARACTER_NUMBER_FOR_VALUE - 1) { + Width = CHARACTER_NUMBER_FOR_VALUE - 1; + } + + if (Value < 0) { + Value = -Value; + ValueIsNegative = TRUE; + } + + do { + TempValue = Value; + Value = (INT64)DivU64x32 ((UINT64)Value, 10); + Remainder = (UINTN)((UINT64)TempValue - 10 * Value); + *(TempStr++) = (CHAR16)(Remainder + '0'); + ValueCharNum++; + Count++; + if ((Flags & COMMA_TYPE) == COMMA_TYPE) { + if (ValueCharNum % 3 == 0 && Value != 0) { + *(TempStr++) = ','; + Count++; + } + } + } while (Value != 0); + + if (ValueIsNegative) { + *(TempStr++) = '-'; + Count++; + } + + if ((Flags & PREFIX_ZERO) && !ValueIsNegative) { + Prefix = '0'; + } else { + Prefix = ' '; + } + + Index = Count; + if (!(Flags & LEFT_JUSTIFY)) { + for (; Index < Width; Index++) { + *(TempStr++) = Prefix; + } + } + + // + // Reverse temp string into Buffer. + // + if (Width > 0 && (UINTN) (TempStr - TempBuffer) > Width) { + TempStr = TempBuffer + Width; + } + Index = 0; + while (TempStr != TempBuffer) { + *(BufferPtr++) = *(--TempStr); + Index++; + } + + *BufferPtr = 0; + return Index; +} + +static CHAR16 mHexStr[] = { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', + L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' }; + +/** + VSPrint worker function that prints a Value as a hex number in Buffer + + @param Buffer Location to place ascii hex string of Value. + @param Value Hex value to convert to a string in Buffer. + @param Flags Flags to use in printing Hex string, see file header for details. + @param Width Width of hex value. + + @retval Number of characters printed. + +**/ +UINTN +EfiValueToHexStr ( + IN OUT CHAR16 *Buffer, + IN UINT64 Value, + IN UINTN Flags, + IN UINTN Width + ) +{ + CHAR16 TempBuffer[CHARACTER_NUMBER_FOR_VALUE]; + CHAR16 *TempStr; + CHAR16 Prefix; + CHAR16 *BufferPtr; + UINTN Count; + UINTN Index; + + TempStr = TempBuffer; + BufferPtr = Buffer; + + // + // Count starts at one since we will null terminate. Each iteration of the + // loop picks off one nibble. Oh yea TempStr ends up backwards + // + Count = 0; + + if (Width > CHARACTER_NUMBER_FOR_VALUE - 1) { + Width = CHARACTER_NUMBER_FOR_VALUE - 1; + } + + do { + Index = ((UINTN)Value & 0xf); + *(TempStr++) = mHexStr[Index]; + Value = RShiftU64 (Value, 4); + Count++; + } while (Value != 0); + + if (Flags & PREFIX_ZERO) { + Prefix = '0'; + } else { + Prefix = ' '; + } + + Index = Count; + if (!(Flags & LEFT_JUSTIFY)) { + for (; Index < Width; Index++) { + *(TempStr++) = Prefix; + } + } + + // + // Reverse temp string into Buffer. + // + if (Width > 0 && (UINTN) (TempStr - TempBuffer) > Width) { + TempStr = TempBuffer + Width; + } + Index = 0; + while (TempStr != TempBuffer) { + *(BufferPtr++) = *(--TempStr); + Index++; + } + + *BufferPtr = 0; + return Index; +} + +/*++ + Converts MAC address to Unicode string. + The value is 64-bit and the resulting string will be 12 + digit hex number in pairs of digits separated by dashes. + + @param String string that will contain the value + @param MacAddr add argument and description to function comment + @param AddrSize add argument and description to function comment + +**/ +CHAR16 * +StrMacToString ( + OUT CHAR16 *String, + IN EFI_MAC_ADDRESS *MacAddr, + IN UINT32 AddrSize + ) +{ + UINT32 i; + + for (i = 0; i < AddrSize; i++) { + + EfiValueToHexStr ( + &String[2 * i], + MacAddr->Addr[i] & 0xFF, + PREFIX_ZERO, + 2 + ); + } + + // + // Terminate the string. + // + String[2 * AddrSize] = L'\0'; + + return String; +} + +VOID UpdateLatestBootTime() { + UINTN VarSize; + EFI_STATUS Status; + UINT64 TimeValue; + CHAR16 Buffer[40]; + if (mSystemConfiguration.LogBootTime != 1) { + return; + } + VarSize = sizeof(TimeValue); + Status = gRT->GetVariable( + BOOT_TIME_NAME, + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &TimeValue + ); + if (EFI_ERROR(Status)) { + return; + } + UnicodeSPrint (Buffer, sizeof (Buffer), L"%d ms", (UINT32)TimeValue); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_LOG_BOOT_TIME_VALUE), Buffer, NULL); +} + +/** + Get Cache Type for the specified Cache. This function is invoked when there is data records + available in the Data Hub. + + Get Cache Type function arguments: + + @param Instance The instance number of the subclass with the same ProducerName.. + @param SubInstance The instance number of the RecordType for the same Instance. + @param CacheType Cache type, see definition of EFI_CACHE_TYPE_DATA. + + @retval EFI_STATUS + +**/ +EFI_STATUS +GetCacheType( + IN UINT16 Instance, + IN UINT16 SubInstance, + IN EFI_CACHE_TYPE_DATA* CacheType) +{ + EFI_STATUS Status; + EFI_DATA_HUB_PROTOCOL *DataHub; + EFI_DATA_RECORD_HEADER *Record; + UINT64 MonotonicCount; + EFI_CACHE_VARIABLE_RECORD* CacheVariableRecord; + EFI_SUBCLASS_TYPE1_HEADER *DataHeader; + + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + (void **)&DataHub + ); + ASSERT_EFI_ERROR(Status); + + // + // Get all available data records from data hub + // + MonotonicCount = 0; + Record = NULL; + + do { + Status = DataHub->GetNextRecord ( + DataHub, + &MonotonicCount, + NULL, + &Record + ); + if (!EFI_ERROR(Status)) { + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) { + DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *)(Record + 1); + + if(CompareGuid(&Record->DataRecordGuid, &gEfiCacheSubClassGuid) && + (DataHeader->RecordType == CacheTypeRecordType) && + (DataHeader->Instance == Instance) && + (DataHeader->SubInstance == SubInstance)) { + CacheVariableRecord = (EFI_CACHE_VARIABLE_RECORD *)(DataHeader + 1); + if(CacheType){ + *CacheType = CacheVariableRecord->CacheType; + return EFI_SUCCESS; + } + } + } + } + } while(!EFI_ERROR(Status) && (MonotonicCount != 0)); + + return EFI_NOT_FOUND; +} + +/** + Setup data filter function. This function is invoked when there is data records + available in the Data Hub. + + + Standard event notification function arguments: + @param Event The event that is signaled. + @param Context Not used here. + + @retval EFI_STATUS + +**/ +VOID +PrepareSetupInformation ( + ) +{ + + EFI_STATUS Status; + EFI_DATA_HUB_PROTOCOL *DataHub; + EFI_DATA_RECORD_HEADER *Record; + UINT8 *SrcData; + UINT32 SrcDataSize; + EFI_SUBCLASS_TYPE1_HEADER *DataHeader; + CHAR16 *NewString; + CHAR16 *NewString2; + CHAR16 *NewStringToken; + STRING_REF TokenToUpdate; + EFI_PROCESSOR_VERSION_DATA *ProcessorVersion; + UINTN Index; + UINT16 EeState; + UINTN DataOutput; + + EFI_PROCESSOR_MICROCODE_REVISION_DATA *CpuUcodeRevisionData; + EFI_MEMORY_ARRAY_START_ADDRESS *MemoryArray; + EFI_MEMORY_ARRAY_LINK *MemoryArrayLink; + UINT64 MonotonicCount; + + CHAR16 Version[100]; //Assuming that strings are < 100 UCHAR + CHAR16 ReleaseDate[100]; //Assuming that strings are < 100 UCHAR + CHAR16 ReleaseTime[100]; //Assuming that strings are < 100 UCHAR + + NewString = AllocateZeroPool (0x100); + NewString2 = AllocateZeroPool (0x100); + SetMem(Version, sizeof(Version), 0); + SetMem(ReleaseDate, sizeof(ReleaseDate), 0); + SetMem(ReleaseTime, sizeof(ReleaseTime), 0); + + // + // Initialize EE state for not to show EE related setup options + // + EeState = 0; + + // + // Get the Data Hub Protocol. Assume only one instance + // + Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (void **)&DataHub); + ASSERT_EFI_ERROR(Status); + + // + // Get all available data records from data hub + // + MonotonicCount = 0; + Record = NULL; + + do { + Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record); + if (!EFI_ERROR(Status)) { + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) { + DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *)(Record + 1); + SrcData = (UINT8 *)(DataHeader + 1); + SrcDataSize = Record->RecordSize - Record->HeaderSize - sizeof (EFI_SUBCLASS_TYPE1_HEADER); + + // + // Processor + // + if (CompareGuid(&Record->DataRecordGuid, &gEfiProcessorSubClassGuid)) { + CopyMem (&mProcessorProducerGuid, &Record->ProducerName, sizeof(EFI_GUID)); + switch (DataHeader->RecordType) { + case ProcessorCoreFrequencyRecordType: + CopyMem(&mProcessorFrequency, SrcData, sizeof(EFI_EXP_BASE10_DATA)); + Index = EfiValueToString ( + NewString, + ConvertBase10ToRaw ((EFI_EXP_BASE10_DATA *)SrcData)/1000000000, + PREFIX_ZERO, + 0 + ); + StrCat (NewString, L"."); + EfiValueToString ( + NewString + Index + 1, + ((ConvertBase10ToRaw ((EFI_EXP_BASE10_DATA *)SrcData)%1000000000)/10000000), + PREFIX_ZERO, + 0 + ); + StrCat (NewString, L" GHz"); + TokenToUpdate = (STRING_REF)STR_PROCESSOR_SPEED_VALUE; + HiiSetString(mHiiHandle, TokenToUpdate, NewString, NULL); + break; + + case ProcessorVersionRecordType: + ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *)SrcData; + NewStringToken = HiiGetPackageString(&mProcessorProducerGuid, *ProcessorVersion, NULL); + TokenToUpdate = (STRING_REF)STR_PROCESSOR_VERSION_VALUE; + HiiSetString(mHiiHandle, TokenToUpdate, NewStringToken, NULL); + break; + case CpuUcodeRevisionDataRecordType: + CpuUcodeRevisionData = (EFI_PROCESSOR_MICROCODE_REVISION_DATA *) SrcData; + if (CpuUcodeRevisionData->ProcessorMicrocodeRevisionNumber != 0) { + EfiValueToHexStr ( + NewString, + CpuUcodeRevisionData->ProcessorMicrocodeRevisionNumber, + PREFIX_ZERO, + 8 + ); + TokenToUpdate = (STRING_REF)STR_PROCESSOR_MICROCODE_VALUE; + HiiSetString(mHiiHandle, TokenToUpdate, NewString, NULL); + } + break; + default: + break; + } + + // + // Cache + // + } else if (CompareGuid(&Record->DataRecordGuid, &gEfiCacheSubClassGuid) && + (DataHeader->RecordType == CacheSizeRecordType)) { + if (DataHeader->SubInstance == EFI_CACHE_L1) { + EFI_CACHE_TYPE_DATA CacheType; + if (EFI_SUCCESS == GetCacheType(DataHeader->Instance, DataHeader->SubInstance,&CacheType)){ + if (CacheType == EfiCacheTypeData) { + TokenToUpdate = (STRING_REF)STR_PROCESSOR_L1_DATA_CACHE_VALUE; + } else if (CacheType == EfiCacheTypeInstruction) { + TokenToUpdate = (STRING_REF)STR_PROCESSOR_L1_INSTR_CACHE_VALUE; + } else { + continue; + } + } else { + continue; + } + } + else if (DataHeader->SubInstance == EFI_CACHE_L2) { + TokenToUpdate = (STRING_REF)STR_PROCESSOR_L2_CACHE_VALUE; + } else { + continue; + } + if (ConvertBase2ToRaw((EFI_EXP_BASE2_DATA *)SrcData)) { + DataOutput = ConvertBase2ToRaw((EFI_EXP_BASE2_DATA *)SrcData) >> 10; + EfiValueToString (NewString, DataOutput, PREFIX_ZERO, 0); + + StrCat (NewString, L" KB"); + if (DataHeader->SubInstance == EFI_CACHE_L3) { + HiiSetString(mHiiHandle, TokenToUpdate, NewString, NULL); + } else if(DataHeader->SubInstance == EFI_CACHE_L2 && mPlatformCpuInfo.CpuPackage.CoresPerPhysicalPackage > 1){ + // + // Show XxL2 string + // + EfiValueToString ( + NewString2, + mPlatformCpuInfo.CpuPackage.CoresPerPhysicalPackage, + PREFIX_ZERO, + 0 + ); + StrCat(NewString2, L"x "); + StrCat(NewString2, NewString); + HiiSetString(mHiiHandle, TokenToUpdate, NewString2, NULL); + } else { + HiiSetString(mHiiHandle, TokenToUpdate, NewString, NULL); + } + } + + // + // Memory + // + } else if (CompareGuid(&Record->DataRecordGuid, &gEfiMemorySubClassGuid)) { + switch (DataHeader->RecordType) { + case EFI_MEMORY_ARRAY_LINK_RECORD_NUMBER: + MemoryArrayLink = (EFI_MEMORY_ARRAY_LINK *)SrcData; + + if (MemoryArrayLink->MemorySpeed > 0) { + // + // Save the lowest speed memory module + // + if (MemoryArrayLink->MemorySpeed < mMemorySpeed) { + mMemorySpeed = MemoryArrayLink->MemorySpeed; + } + switch (DataHeader->SubInstance) { + case 1: + mMemorySpeedChannelASlot0 = MemoryArrayLink->MemorySpeed; + mMemorySizeChannelASlot0 = MemoryArrayLink->MemoryDeviceSize; + break; + case 2: + mMemorySpeedChannelASlot1 = MemoryArrayLink->MemorySpeed; + mMemorySizeChannelASlot1 = MemoryArrayLink->MemoryDeviceSize; + break; + case 3: + mMemorySpeedChannelBSlot0 = MemoryArrayLink->MemorySpeed; + mMemorySizeChannelBSlot0 = MemoryArrayLink->MemoryDeviceSize; + break; + case 4: + mMemorySpeedChannelBSlot1 = MemoryArrayLink->MemorySpeed; + mMemorySizeChannelBSlot1 = MemoryArrayLink->MemoryDeviceSize; + break; + case 5: + mMemorySpeedChannelCSlot0 = MemoryArrayLink->MemorySpeed; + mMemorySizeChannelCSlot0 = MemoryArrayLink->MemoryDeviceSize; + break; + case 6: + mMemorySpeedChannelCSlot1 = MemoryArrayLink->MemorySpeed; + mMemorySizeChannelCSlot1 = MemoryArrayLink->MemoryDeviceSize; + break; + default: + break; + } + } + break; + + case EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER: + MemoryArray = (EFI_MEMORY_ARRAY_START_ADDRESS *)SrcData; + if (MemoryArray->MemoryArrayEndAddress - MemoryArray->MemoryArrayStartAddress) { + DataOutput = (UINTN)RShiftU64((MemoryArray->MemoryArrayEndAddress - MemoryArray->MemoryArrayStartAddress + 1), 20); + EfiValueToString (NewString, DataOutput / 1024, PREFIX_ZERO, 0); + if(DataOutput % 1024) { + StrCat (NewString, L"."); + DataOutput = ((DataOutput % 1024) * 1000) / 1024; + while(!(DataOutput % 10)) + DataOutput = DataOutput / 10; + EfiValueToString (NewString2, DataOutput, PREFIX_ZERO, 0); + StrCat (NewString, NewString2); + } + StrCat (NewString, L" GB"); + TokenToUpdate = (STRING_REF)STR_TOTAL_MEMORY_SIZE_VALUE; + HiiSetString(mHiiHandle, TokenToUpdate, NewString, NULL); + } + break; + + default: + break; + } + } + } + } + } while (!EFI_ERROR(Status) && (MonotonicCount != 0)); + + Status = GetBiosVersionDateTime ( + Version, + ReleaseDate, + ReleaseTime + ); + + DEBUG ((EFI_D_ERROR, "GetBiosVersionDateTime :%s %s %s \n", Version, ReleaseDate, ReleaseTime)); + if (!EFI_ERROR (Status)) { + UINTN Length = 0; + CHAR16 *BuildDateTime; + + Length = StrLen(ReleaseDate) + StrLen(ReleaseTime); + + BuildDateTime = AllocateZeroPool ((Length+2) * sizeof(CHAR16)); + StrCpy (BuildDateTime, ReleaseDate); + StrCat (BuildDateTime, L" "); + StrCat (BuildDateTime, ReleaseTime); + + TokenToUpdate = (STRING_REF)STR_BIOS_VERSION_VALUE; + DEBUG ((EFI_D_ERROR, "update STR_BIOS_VERSION_VALUE\n")); + HiiSetString(mHiiHandle, TokenToUpdate, Version, NULL); + + TokenToUpdate = (STRING_REF)STR_BIOS_BUILD_TIME_VALUE; + DEBUG ((EFI_D_ERROR, "update STR_BIOS_BUILD_TIME_VALUE\n")); + HiiSetString(mHiiHandle, TokenToUpdate, BuildDateTime, NULL); + } + + // + // Calculate and update memory speed display in Main Page + // + // + // Update the overall memory speed + // + if (mMemorySpeed != 0xffff) { + EfiValueToString (NewString, mMemorySpeed, PREFIX_ZERO, 0); + StrCat (NewString, L" MHz"); + + TokenToUpdate = (STRING_REF)STR_SYSTEM_MEMORY_SPEED_VALUE; + HiiSetString(mHiiHandle, TokenToUpdate, NewString, NULL); + } + + gBS->FreePool(NewString); + gBS->FreePool(NewString2); + + return; +} + +/** + + Routine Description: update the SETUP info for "Additional Information" which is SMBIOS info. + + @retval EFI_STATUS + +**/ +EFI_STATUS +UpdateAdditionalInformation ( + ) +{ + EFI_STATUS Status; + UINT64 MonotonicCount; + EFI_DATA_HUB_PROTOCOL *DataHub; + EFI_DATA_RECORD_HEADER *Record; + EFI_SUBCLASS_TYPE1_HEADER *DataHeader; + EFI_MISC_SYSTEM_MANUFACTURER *SystemManufacturer; + UINTN Size; + EFI_SMBIOS_PROTOCOL *Smbios; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_TABLE_HEADER *SmbiosRecord; + SMBIOS_TABLE_TYPE0 *Type0Record; + UINT8 StrIndex; + CHAR16 *BiosVersion = NULL; + CHAR16 *IfwiVersion = NULL; + UINT16 SearchIndex; + EFI_STRING_ID TokenToUpdate; + + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + (void **)&DataHub + ); + + ASSERT_EFI_ERROR(Status); + + Size = 3; + + MonotonicCount = 0; + Record = NULL; + do { + Status = DataHub->GetNextRecord ( + DataHub, + &MonotonicCount, + NULL, + &Record + ); + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) { + DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *)(Record + 1); + + if (CompareGuid(&Record->DataRecordGuid, &gEfiMiscSubClassGuid) && + (DataHeader->RecordType == EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER)) { + // + // System Information + // + SystemManufacturer = (EFI_MISC_SYSTEM_MANUFACTURER *)(DataHeader + 1); + +#if defined( RVP_SUPPORT ) && RVP_SUPPORT + // + // UUID (System Information) + // + SMBIOSString = EfiLibAllocateZeroPool (0x100); + GuidToString ( &SystemManufacturer->SystemUuid, SMBIOSString, 0x00 ); + + TokenToUpdate = (STRING_REF)STR_SYSTEM_UUID_VALUE; + HiiSetString(mHiiHandle, TokenToUpdate, SMBIOSString, NULL); + + gBS->FreePool(SMBIOSString); +#endif + } + } + } while (!EFI_ERROR(Status) && (MonotonicCount != 0)); + + Status = gBS->LocateProtocol ( + &gEfiSmbiosProtocolGuid, + NULL, + (VOID **) &Smbios + ); + ASSERT_EFI_ERROR (Status); + + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + do { + Status = Smbios->GetNext ( + Smbios, + &SmbiosHandle, + NULL, + &SmbiosRecord, + NULL + ); + if (SmbiosRecord->Type == EFI_SMBIOS_TYPE_BIOS_INFORMATION) { + Type0Record = (SMBIOS_TABLE_TYPE0 *) SmbiosRecord; + StrIndex = Type0Record->BiosVersion; + GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &BiosVersion); + TokenToUpdate = STRING_TOKEN (STR_BIOS_VERSION_VALUE); + for (SearchIndex = 0x0; SearchIndex < SMBIOS_STRING_MAX_LENGTH; SearchIndex++) { + if (BiosVersion[SearchIndex] == 0x0020) { + BiosVersion[SearchIndex] = 0x0000; + IfwiVersion = (CHAR16 *)(&BiosVersion[SearchIndex+1]); + break; + } else if (BiosVersion[SearchIndex] == 0x0000) { + break; + } + } + HiiSetString (mHiiHandle, TokenToUpdate, BiosVersion, NULL); + + // + // Check IfwiVersion, to avoid no IFWI version in SMBIOS Type 0 strucntion + // + if(IfwiVersion) { + TokenToUpdate = STRING_TOKEN (STR_IFWI_VERSION_VALUE); + HiiSetString (mHiiHandle, TokenToUpdate, IfwiVersion, NULL); + } + } + } while (!EFI_ERROR(Status)); + + UpdateLatestBootTime(); + + return EFI_SUCCESS; +} + +VOID +UpdateCPUInformation () +{ + CHAR16 Buffer[40]; + UINT16 FamilyId; + UINT8 Model; + UINT8 SteppingId; + UINT8 ProcessorType; + EFI_STATUS Status; + EFI_MP_SERVICES_PROTOCOL *MpService; + UINTN MaximumNumberOfCPUs; + UINTN NumberOfEnabledCPUs; + UINT32 Buffer32 = 0xFFFFFFFF; // Keep buffer with unknown device + + EfiCpuVersion (&FamilyId, &Model, &SteppingId, &ProcessorType); + + // + //we need raw Model data + // + Model = Model & 0xf; + + // + //Family/Model/Step + // + UnicodeSPrint (Buffer, sizeof (Buffer), L"%d/%d/%d", FamilyId, Model, SteppingId); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_PROCESSOR_ID_VALUE), Buffer, NULL); + + Status = gBS->LocateProtocol ( + &gEfiMpServiceProtocolGuid, + NULL, + (void **)&MpService + ); + if (!EFI_ERROR (Status)) { + // + // Determine the number of processors + // + MpService->GetNumberOfProcessors ( + MpService, + &MaximumNumberOfCPUs, + &NumberOfEnabledCPUs + ); + UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", MaximumNumberOfCPUs); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_PROCESSOR_CORE_VALUE), Buffer, NULL); + } + // + // Update Mobile / Desktop / Tablet SKU + // + Buffer32 =(UINT32) RShiftU64 (EfiReadMsr (MSR_IA32_PLATFORM_ID), 50) & 0x07; + + switch(Buffer32){ + case 0x0: + UnicodeSPrint (Buffer, sizeof (Buffer), L"(%d) - ISG SKU SOC", Buffer32); + break; + case 0x01: + UnicodeSPrint (Buffer, sizeof (Buffer), L"(%d) - Mobile SKU SOC", Buffer32); + break; + case 0x02: + UnicodeSPrint (Buffer, sizeof (Buffer), L"(%d) - Desktop SKU SOC", Buffer32); + break; + case 0x03: + UnicodeSPrint (Buffer, sizeof (Buffer), L"(%d) - Mobile SKU SOC", Buffer32); + break; + default: + UnicodeSPrint (Buffer, sizeof (Buffer), L"(%d) - Unknown SKU SOC", Buffer32); + break; + } + HiiSetString(mHiiHandle,STRING_TOKEN(STR_PROCESSOR_SKU_VALUE), Buffer, NULL); + +} + + +EFI_STATUS +SearchChildHandle( + EFI_HANDLE Father, + EFI_HANDLE *Child + ) +{ + EFI_STATUS Status; + UINTN HandleIndex; + EFI_GUID **ProtocolGuidArray = NULL; + UINTN ArrayCount; + UINTN ProtocolIndex; + UINTN OpenInfoCount; + UINTN OpenInfoIndex; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo = NULL; + UINTN mHandleCount; + EFI_HANDLE *mHandleBuffer= NULL; + + // + // Retrieve the list of all handles from the handle database + // + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &mHandleCount, + &mHandleBuffer + ); + + for (HandleIndex = 0; HandleIndex < mHandleCount; HandleIndex++) + { + // + // Retrieve the list of all the protocols on each handle + // + Status = gBS->ProtocolsPerHandle ( + mHandleBuffer[HandleIndex], + &ProtocolGuidArray, + &ArrayCount + ); + if (!EFI_ERROR (Status)) + { + for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) + { + Status = gBS->OpenProtocolInformation ( + mHandleBuffer[HandleIndex], + ProtocolGuidArray[ProtocolIndex], + &OpenInfo, + &OpenInfoCount + ); + if (!EFI_ERROR (Status)) + { + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) + { + if(OpenInfo[OpenInfoIndex].AgentHandle == Father) + { + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) + { + *Child = mHandleBuffer[HandleIndex]; + Status = EFI_SUCCESS; + goto TryReturn; + } + } + } + Status = EFI_NOT_FOUND; + } + } + if(OpenInfo != NULL) + { + FreePool(OpenInfo); + OpenInfo = NULL; + } + } + FreePool (ProtocolGuidArray); + ProtocolGuidArray = NULL; + } +TryReturn: + if(OpenInfo != NULL) + { + FreePool (OpenInfo); + OpenInfo = NULL; + } + if(ProtocolGuidArray != NULL) + { + FreePool(ProtocolGuidArray); + ProtocolGuidArray = NULL; + } + if(mHandleBuffer != NULL) + { + FreePool (mHandleBuffer); + mHandleBuffer = NULL; + } + return Status; +} + +EFI_STATUS +JudgeHandleIsPCIDevice( + EFI_HANDLE Handle, + UINT8 Device, + UINT8 Funs + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH *DPath; + EFI_DEVICE_PATH *DevicePath; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DPath + ); + if(!EFI_ERROR(Status)) + { + DevicePath = DPath; + while(!IsDevicePathEnd(DPath)) + { + if((DPath->Type == HARDWARE_DEVICE_PATH) && (DPath->SubType == HW_PCI_DP)) + { + PCI_DEVICE_PATH *PCIPath; + + PCIPath = (PCI_DEVICE_PATH*) DPath; + DPath = NextDevicePathNode(DPath); + if(IsDevicePathEnd(DPath) && (PCIPath->Device == Device) && (PCIPath->Function == Funs)) + { + return EFI_SUCCESS; + } + } + else + { + DPath = NextDevicePathNode(DPath); + } + } + } + return EFI_UNSUPPORTED; +} + +EFI_STATUS +GetDriverName( + EFI_HANDLE Handle, + CHAR16 *Name + ) +{ + EFI_DRIVER_BINDING_PROTOCOL *BindHandle = NULL; + EFI_STATUS Status; + UINT32 Version; + UINT16 *Ptr; + Status = gBS->OpenProtocol( + Handle, + &gEfiDriverBindingProtocolGuid, + (VOID**)&BindHandle, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR(Status)) + { + return EFI_NOT_FOUND; + } + + Version = BindHandle->Version; + Ptr = (UINT16*)&Version; + UnicodeSPrint(Name, 40, L"%d.%d.%d", Version >> 24 , (Version >>16)& 0x0f ,*(Ptr)); + + return EFI_SUCCESS; +} + +EFI_STATUS +GetGOPDriverName( + CHAR16 *Name + ) +{ + UINTN HandleCount; + EFI_HANDLE *Handles= NULL; + UINTN Index; + EFI_STATUS Status; + EFI_HANDLE Child = 0; + + Status = gBS->LocateHandleBuffer( + ByProtocol, + &gEfiDriverBindingProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + for (Index = 0; Index < HandleCount ; Index++) + { + Status = SearchChildHandle(Handles[Index], &Child); + if(!EFI_ERROR(Status)) + { + Status = JudgeHandleIsPCIDevice( + Child, + 0x02, + 0x00 + ); + if(!EFI_ERROR(Status)) + { + return GetDriverName(Handles[Index], Name); + } + } + } + return EFI_UNSUPPORTED; +} + +EFI_STATUS +UpdatePlatformInformation ( + ) +{ + UINT32 MicroCodeVersion; + CHAR16 Buffer[40]; + UINT8 IgdVBIOSRevH; + UINT8 IgdVBIOSRevL; + UINT16 EDX; + EFI_IA32_REGISTER_SET RegSet; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios = NULL; + EFI_STATUS Status; + UINT8 CpuFlavor=0; + EFI_PEI_HOB_POINTERS GuidHob; + EFI_PLATFORM_INFO_HOB *mPlatformInfo=NULL; + UINTN NumHandles; + EFI_HANDLE *HandleBuffer; + UINTN Index; + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy; + UINTN PciD31F0RegBase; + UINT8 count; + UINT8 Data8; + UINT8 PIDData8; + + CHAR16 Name[40]; + UINT32 MrcVersion; + + // + // Get the HOB list. If it is not present, then ASSERT. + // + GuidHob.Raw = GetHobList (); + if (GuidHob.Raw != NULL) { + if ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformInfoGuid, GuidHob.Raw)) != NULL) { + mPlatformInfo = GET_GUID_HOB_DATA (GuidHob.Guid); + } + } + + // + //VBIOS version + // + Status = gBS->LocateProtocol( + &gEfiLegacyBiosProtocolGuid, + NULL, + (void **)&LegacyBios + ); + if (!EFI_ERROR (Status)) { + RegSet.X.AX = 0x5f01; + Status = LegacyBios->Int86 (LegacyBios, 0x10, &RegSet); + ASSERT_EFI_ERROR(Status); + + // + // simulate AMI int15 (ax=5f01) handler + // check NbInt15.asm in AMI code for asm edition + // + EDX = (UINT16)((RegSet.E.EBX >> 16) & 0xffff); + IgdVBIOSRevH = (UINT8)(((EDX & 0x0F00) >> 4) | (EDX & 0x000F)); + IgdVBIOSRevL = (UINT8)(((RegSet.X.BX & 0x0F00) >> 4) | (RegSet.X.BX & 0x000F)); + + if (IgdVBIOSRevH==0 && IgdVBIOSRevL==0){ + HiiSetString(mHiiHandle, STRING_TOKEN(STR_CHIP_IGD_VBIOS_REV_VALUE), L"N/A", NULL); + } else { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%02X%02X", IgdVBIOSRevH,IgdVBIOSRevL); + HiiSetString(mHiiHandle, STRING_TOKEN(STR_CHIP_IGD_VBIOS_REV_VALUE), Buffer, NULL); + } + } + + Status = GetGOPDriverName(Name); + + if (!EFI_ERROR(Status)) + { + HiiSetString(mHiiHandle, STRING_TOKEN(STR_GOP_VALUE), Name, NULL); + } + + + // + // CpuFlavor + // ISG-DC Tablet 000 + // VLV-QC Tablet 001 + // VLV-QC Desktop 010 + // VLV-QC Notebook 011 + // + CpuFlavor = RShiftU64 (EfiReadMsr (MSR_IA32_PLATFORM_ID), 50) & 0x07; + + switch(CpuFlavor){ + case 0x0: + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s (%01x)", L"VLV-DC Tablet", CpuFlavor); + break; + case 0x01: + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s (%01x)", L"VLV-QC Notebook", CpuFlavor); + break; + case 0x02: + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s (%01x)", L"VLV-QC Desktop", CpuFlavor); + break; + case 0x03: + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s (%01x)", L"VLV-QC Notebook", CpuFlavor); + break; + default: + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s (%01x)", L"Unknown CPU", CpuFlavor); + break; + } + HiiSetString(mHiiHandle,STRING_TOKEN(STR_CPU_FLAVOR_VALUE), Buffer, NULL); + + if ( NULL != mPlatformInfo) { + // + //BoardId + // + switch(mPlatformInfo->BoardId){ + case 0x2: + UnicodeSPrint (Buffer, sizeof (Buffer), L"BAY LAKE RVP(%02x)", mPlatformInfo->BoardId); + break; + + case 0x4: + UnicodeSPrint (Buffer, sizeof (Buffer), L"BAY LAKE FFRD(%02x)", mPlatformInfo->BoardId); + break; + + case 0x5: + UnicodeSPrint (Buffer, sizeof (Buffer), L"BAY ROCK RVP DDR3L (%02x)", mPlatformInfo->BoardId); + break; + + case 0x20: + UnicodeSPrint (Buffer, sizeof (Buffer), L"BAYLEY BAY (%02x)", mPlatformInfo->BoardId); + break; + + case 0x30: + UnicodeSPrint (Buffer, sizeof (Buffer), L"BAKER SPORT (%02x)", mPlatformInfo->BoardId); + break; + + case 0x0: + UnicodeSPrint (Buffer, sizeof (Buffer), L"ALPINE VALLEY (%x)", mPlatformInfo->BoardId); + break; + + case 0x3: + UnicodeSPrint (Buffer, sizeof (Buffer), L"BAY LAKE FFD8 (%x)", mPlatformInfo->BoardId); + break; + + default: + UnicodeSPrint (Buffer, sizeof (Buffer), L"Unknown BOARD (%02x)", mPlatformInfo->BoardId); + break; + } + HiiSetString(mHiiHandle,STRING_TOKEN(STR_BOARD_ID_VALUE), Buffer, NULL); + + + // + // Get Board FAB ID Info from protocol, update into the NVS area. + // bit0~bit3 are for Fab ID, 0x0F means unknow FAB. + // + if(mPlatformInfo->BoardRev == 0x0F) { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", L"Unknown FAB"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_FAB_ID_VALUE), Buffer, NULL); + } else { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%2x", mPlatformInfo->BoardRev); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_FAB_ID_VALUE), Buffer, NULL); + } + } + + // + //Update MRC Version + // + MrcVersion = 0x00000000; + MrcVersion &= 0xffff; + Index = EfiValueToString (Buffer, MrcVersion/100, PREFIX_ZERO, 0); + StrCat (Buffer, L"."); + EfiValueToString (Buffer + Index + 1, (MrcVersion%100)/10, PREFIX_ZERO, 0); + EfiValueToString (Buffer + Index + 2, (MrcVersion%100)%10, PREFIX_ZERO, 0); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MRC_VERSION_VALUE), Buffer, NULL); + + // + //Update Soc Version + // + + // + // Retrieve all instances of PCH Platform Policy protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gDxePchPlatformPolicyProtocolGuid, + NULL, + &NumHandles, + &HandleBuffer + ); + if (!EFI_ERROR (Status)) { + // + // Find the matching PCH Policy protocol + // + for (Index = 0; Index < NumHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gDxePchPlatformPolicyProtocolGuid, + (void **)&PchPlatformPolicy + ); + if (!EFI_ERROR (Status)) { + PciD31F0RegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + + Data8 = MmioRead8 (PciD31F0RegBase + R_PCH_LPC_RID_CC); + count = sizeof (SBRevisionTable) / sizeof (SBRevisionTable[0]); + for (Index = 0; Index < count; Index++) { + if(Data8 == SBRevisionTable[Index].RevId) { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%02x %a", Data8, SBRevisionTable[Index].String); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_SOC_VALUE), Buffer, NULL); + break; + } + } + break; + } + } + } + + // + // Microcode Revision + // + EfiWriteMsr (EFI_MSR_IA32_BIOS_SIGN_ID, 0); + EfiCpuid (EFI_CPUID_VERSION_INFO, NULL); + MicroCodeVersion = (UINT32) RShiftU64 (EfiReadMsr (EFI_MSR_IA32_BIOS_SIGN_ID), 32); + UnicodeSPrint (Buffer, sizeof (Buffer), L"%x", MicroCodeVersion); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_PROCESSOR_MICROCODE_VALUE), Buffer, NULL); + + // + // Punit Version + // + Data8 = 0; + UnicodeSPrint (Buffer, sizeof (Buffer), L"0x%x", Data8); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_PUNIT_FW_VALUE), Buffer, NULL); + + // + // PMC Version + // + Data8 = (UINT8)((MmioRead32 (PMC_BASE_ADDRESS + R_PCH_PMC_PRSTS)>>16)&0x00FF); + PIDData8 = (UINT8)((MmioRead32 (PMC_BASE_ADDRESS + R_PCH_PMC_PRSTS)>>24)&0x00FF); + UnicodeSPrint (Buffer, sizeof (Buffer), L"0x%X_%X",PIDData8, Data8); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_PMC_FW_VALUE), Buffer, NULL); + + return EFI_SUCCESS; +} + +/** + + Update SATA Drivesize Strings for Setup and Boot order + + @param NewString - pointer to string. + @param DeviceSpeed - speed of drive. + +**/ +VOID +GetDeviceSpeedString ( + CHAR16 *NewString, + IN UINTN DeviceSpeed + ) +{ + if (DeviceSpeed == 0x01) { + StrCat (NewString, L"1.5Gb/s"); + } else if (DeviceSpeed == 0x02) { + StrCat (NewString, L"3.0Gb/s"); + } else if (DeviceSpeed == 0x03) { + StrCat (NewString, L"6.0Gb/s"); + } else if (DeviceSpeed == 0x0) { + + } +} + +UINT8 +GetChipsetSataPortSpeed ( + UINTN PortNum + ) +{ + UINT32 DeviceSpeed; + UINT8 DeviceConfigStatus; + UINT32 IdeAhciBar; + EFI_PHYSICAL_ADDRESS MemBaseAddress = 0; + UINT8 FunNum; + EFI_STATUS Status; + UINT32 DwordReg; + + + DeviceSpeed = 0x01; // generation 1 + + + // + // Allocate the AHCI BAR + // + FunNum = PCI_FUNCTION_NUMBER_PCH_SATA; + MemBaseAddress = 0x0ffffffff; + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateMaxAddressSearchBottomUp, + EfiGcdMemoryTypeMemoryMappedIo, + N_PCH_SATA_ABAR_ALIGNMENT, // 2^11: 2K Alignment + V_PCH_SATA_ABAR_LENGTH, // 2K Length + &MemBaseAddress, + mImageHandle, + NULL + ); + IdeAhciBar = MmioRead32 ( + MmPciAddress ( + 0, + 0, + PCI_DEVICE_NUMBER_PCH_SATA, + FunNum, + R_PCH_SATA_ABAR + ) + ); + IdeAhciBar &= 0xFFFFF800; + DeviceConfigStatus = 0; + if (IdeAhciBar == 0) { + DeviceConfigStatus = 1; + IdeAhciBar = (UINT32)MemBaseAddress; + MmioWrite32 ( + MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_SATA, FunNum, R_PCH_SATA_ABAR), + IdeAhciBar + ); + MmioOr16 ( + MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_SATA, FunNum, R_PCH_SATA_COMMAND), + B_PCH_SATA_COMMAND_MSE + ); + } + + if (mSystemConfiguration.SataType == PCH_SATA_MODE_IDE){ + // + // Program the "Ports Implemented Register" + // + MmioAndThenOr32 (IdeAhciBar + R_PCH_SATA_AHCI_PI, (UINT32)~(B_PCH_SATA_PORT0_IMPLEMENTED + B_PCH_SATA_PORT1_IMPLEMENTED), (UINT32)(B_PCH_SATA_PORT0_IMPLEMENTED + B_PCH_SATA_PORT1_IMPLEMENTED)); + DwordReg = MmioRead32 (IdeAhciBar + R_PCH_SATA_AHCI_PI); + } + + switch (PortNum) + { + case 0: + DeviceSpeed = *(volatile UINT32 *)(UINTN)(IdeAhciBar + R_PCH_SATA_AHCI_P0SSTS); + break; + case 1: + DeviceSpeed = *(volatile UINT32 *)(UINTN)(IdeAhciBar + R_PCH_SATA_AHCI_P1SSTS); + break; + } + + if (MemBaseAddress) { + gDS->FreeMemorySpace ( + MemBaseAddress, + V_PCH_SATA_ABAR_LENGTH + ); + } + + if (DeviceConfigStatus) { + IdeAhciBar = 0; + MmioWrite32 ( + MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_SATA, FunNum, R_PCH_SATA_ABAR), + IdeAhciBar + ); + } + + DeviceSpeed = (UINT8)((DeviceSpeed >> 4) & 0x0F); + + return (UINT8)DeviceSpeed; +} + +/** + + IDE data filter function. + +**/ +void +IdeDataFilter (void) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_DISK_INFO_PROTOCOL *DiskInfo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath, *DevicePathNode; + PCI_DEVICE_PATH *PciDevicePath; + UINTN Index; + UINT8 Index1; + UINT32 BufferSize; + UINT32 DriveSize; + UINT32 IdeChannel; + UINT32 IdeDevice; + EFI_ATA_IDENTIFY_DATA *IdentifyDriveInfo; + CHAR16 *NewString; + CHAR16 SizeString[20]; + STRING_REF NameToUpdate; + CHAR8 StringBuffer[0x100]; + UINT32 DeviceSpeed; + UINTN PortNumber; + + // + // Assume no line strings is longer than 256 bytes. + // + NewString = AllocateZeroPool (0x100); + PciDevicePath = NULL; + + // + // Fill IDE Infomation + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDiskInfoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + if (EFI_ERROR (Status)) { + return; + } + + for (Index = 0; Index < HandleCount; Index++) { + + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + (VOID*)&DevicePath + ); + ASSERT_EFI_ERROR (Status); + + DevicePathNode = DevicePath; + while (!IsDevicePathEnd (DevicePathNode) ) { + if ((DevicePathType (DevicePathNode) == HARDWARE_DEVICE_PATH) && + ( DevicePathSubType (DevicePathNode) == HW_PCI_DP)) { + PciDevicePath = (PCI_DEVICE_PATH *) DevicePathNode; + break; + } + DevicePathNode = NextDevicePathNode (DevicePathNode); + } + + if (PciDevicePath == NULL) { + continue; + } + + // + // Check for onboard IDE + // + if (PciDevicePath->Device== PCI_DEVICE_NUMBER_PCH_SATA) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiDiskInfoProtocolGuid, + (void **)&DiskInfo + ); + ASSERT_EFI_ERROR (Status); + + Status = DiskInfo->WhichIde ( + DiskInfo, + &IdeChannel, + &IdeDevice + ); + ASSERT_EFI_ERROR (Status); + + IdentifyDriveInfo = AllocatePool (sizeof(EFI_ATA_IDENTIFY_DATA)); + + BufferSize = sizeof(EFI_ATA_IDENTIFY_DATA); + Status = DiskInfo->Identify ( + DiskInfo, + IdentifyDriveInfo, + &BufferSize + ); + ASSERT_EFI_ERROR(Status); + + // + // Onboard SATA Devices + // + if (PciDevicePath->Function == PCI_FUNCTION_NUMBER_PCH_SATA) { + if (IdeChannel == 0 && IdeDevice == 0) { + NameToUpdate = (STRING_REF)STR_SATA0_NAME; + } else if (IdeChannel == 1 && IdeDevice == 0) { + NameToUpdate = (STRING_REF)STR_SATA1_NAME; + } else { + continue; + } + } else { + continue; + } + + ZeroMem(StringBuffer, sizeof(StringBuffer)); + CopyMem( + StringBuffer, + (CHAR8 *)&IdentifyDriveInfo->ModelName, + sizeof(IdentifyDriveInfo->ModelName) + ); + SwapEntries(StringBuffer); + AsciiToUnicode(StringBuffer, NewString); + + // + // Chap it off after 16 characters + // + NewString[16] = 0; + + // + // For HardDisk append the size. Otherwise display atapi + // + if ((IdentifyDriveInfo->config & 0x8000) == 00) { + // + // 48 bit address feature set is supported, get maximum capacity + // + if ((IdentifyDriveInfo->command_set_supported_83 & 0x0400) == 0) { + DriveSize = (((((IdentifyDriveInfo->user_addressable_sectors_hi << 16) + + IdentifyDriveInfo->user_addressable_sectors_lo) / 1000) * 512) / 1000); + } else { + DriveSize = IdentifyDriveInfo->maximum_lba_for_48bit_addressing[0]; + for (Index1 = 1; Index1 < 4; Index1++) { + // + // Lower byte goes first: word[100] is the lowest word, word[103] is highest + // + DriveSize |= LShiftU64(IdentifyDriveInfo->maximum_lba_for_48bit_addressing[Index1], 16 * Index1); + } + DriveSize = (UINT32) DivU64x32(MultU64x32(DivU64x32(DriveSize, 1000), 512), 1000); + } + + StrCat (NewString, L"("); + EfiValueToString (SizeString, DriveSize/1000, PREFIX_BLANK, 0); + StrCat (NewString, SizeString); + StrCat (NewString, L"."); + EfiValueToString (SizeString, (DriveSize%1000)/100, PREFIX_BLANK, 0); + StrCat (NewString, SizeString); + StrCat (NewString, L"GB"); + } else { + StrCat (NewString, L"(ATAPI"); + } + + // + // Update SPEED. + // + PortNumber = (IdeDevice << 1) + IdeChannel; + DeviceSpeed = GetChipsetSataPortSpeed(PortNumber); + + if (DeviceSpeed) { + StrCat (NewString, L"-"); + GetDeviceSpeedString( NewString, DeviceSpeed); + } + + StrCat (NewString, L")"); + + HiiSetString(mHiiHandle, NameToUpdate, NewString, NULL); + + } + } + + if (HandleBuffer != NULL) { + gBS->FreePool (HandleBuffer); + } + + gBS->FreePool(NewString); + + return; +} + + +VOID +EFIAPI +SetupInfo (void) +{ + EFI_STATUS Status; + UINTN VarSize; + EFI_PEI_HOB_POINTERS GuidHob; + + if (mSetupInfoDone) { + return; + } + + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = gRT->GetVariable( + NORMAL_SETUP_NAME, + &gEfiNormalSetupGuid, + NULL, + &VarSize, + &mSystemConfiguration + ); + + ASSERT_EFI_ERROR (Status); + + // + // Update HOB variable for PCI resource information + // Get the HOB list. If it is not present, then ASSERT. + // + GuidHob.Raw = GetHobList (); + if (GuidHob.Raw != NULL) { + if ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformInfoGuid, GuidHob.Raw)) != NULL) { + mPlatformInfo = GET_GUID_HOB_DATA (GuidHob.Guid); + } + } + + + PrepareSetupInformation(); + UpdateAdditionalInformation (); + UpdatePlatformInformation(); + UpdateCPUInformation(); + IdeDataFilter(); + mSetupInfoDone = TRUE; + + return; +} + + +#define EFI_SECURE_BOOT_MODE_NAME L"SecureBoot" + +VOID +CheckSystemConfigLoad(SYSTEM_CONFIGURATION *SystemConfigPtr) +{ + EFI_STATUS Status; + UINT8 SecureBoot; + UINTN DataSize; + + + DataSize = sizeof(SecureBoot); + Status = gRT->GetVariable ( + EFI_SECURE_BOOT_MODE_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + &SecureBoot + ); + + if (EFI_ERROR(Status)) { + SystemConfigPtr->SecureBoot = 0; + } else { + SystemConfigPtr->SecureBoot = SecureBoot; + } +} + + +// +// "SecureBootEnable" variable for the Secure boot feature enable/disable. +// +#define EFI_SECURE_BOOT_ENABLE_NAME L"SecureBootEnable" +extern EFI_GUID gEfiSecureBootEnableDisableGuid; + + +VOID +CheckSystemConfigSave(SYSTEM_CONFIGURATION *SystemConfigPtr) +{ + EFI_STATUS Status; + UINT8 SecureBootCfg; + BOOLEAN SecureBootNotFound; + UINTN DataSize; + + + // + // Secure Boot configuration changes + // + DataSize = sizeof(SecureBootCfg); + SecureBootNotFound = FALSE; + Status = gRT->GetVariable ( + EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, + NULL, + &DataSize, + &SecureBootCfg + ); + + if (EFI_ERROR(Status)) { + SecureBootNotFound = TRUE; + } + if (SecureBootNotFound) { + Status = gRT->GetVariable ( + EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, + NULL, + &DataSize, + &SecureBootCfg + ); + ASSERT_EFI_ERROR(Status); + } + if ((SecureBootCfg) != SystemConfigPtr->SecureBoot) { + SecureBootCfg = !SecureBootCfg; + Status = gRT->SetVariable ( + EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (UINT8), + &SecureBootCfg + ); + } + +} + +VOID +ConfirmSecureBootTest() +{ + +} + diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/SouthClusterConfig.vfi b/Vlv2TbltDevicePkg/PlatformSetupDxe/SouthClusterConfig.vfi new file mode 100644 index 0000000000..e7e952fe96 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/SouthClusterConfig.vfi @@ -0,0 +1,918 @@ +// +// +// Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials are licensed and made available under +// the terms and conditions of the BSD License that accompanies this distribution. +// The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// +// +// +// Module Name: +// +// SourthClusterConfig.vfi +// +// Abstract: +// +// Driver Setup formset. +// +//Revision History: +// ------------------------------------------------------------------------------ +// Rev Date Name Description +// ------------------------------------------------------------------------------ + +// --*/ + +// +// South Cluster Configuration Form +// + +form formid = SOUTH_CLUSTER_FORM_ID, + title = STRING_TOKEN(STR_SOUTH_CLUSTER_TITLE); + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + // + // Jump to PCIe Configuration Form + // + goto PCIE_DEVICE_OPTIONS_FORM_ID, + prompt = STRING_TOKEN(STR_PCIE_OPTIONS_FORM_TITLE), + help = STRING_TOKEN(STR_PCIE_OPTIONS_FORM_HELP); + + // + // Jump to USB Configuration Form + // + goto USB_OPTIONS_FORM_ID, + prompt = STRING_TOKEN(STR_USB_OPTIONS_FORM_TITLE), + help = STRING_TOKEN(STR_USB_OPTIONS_FORM_HELP); + // + // Jump to Azalia Configuration Form + // + goto AZALIA_OPTIONS_FORM_ID, + prompt = STRING_TOKEN(STR_AZALIA_OPTIONS_FORM_TITLE), + help = STRING_TOKEN(STR_AZALIA_OPTIONS_FORM_HELP); + + // + // Jump to Drive Configuration Form + // + goto DRIVE_CONFIGURATION_ID, + prompt = STRING_TOKEN(STR_IDE_FORM_TITLE), + help = STRING_TOKEN(STR_IDE_FORM_HELP); + // + // Jump to LAN Configuration Form + // + + // + // Jump to LPSS Configuration Form + // + goto LPSS_CONFIGURATION_ID, + prompt = STRING_TOKEN(STR_LPSS_SCC_FORM_TITLE), + help = STRING_TOKEN(STR_LPSS_SCC_FORM_HELP); + + // + // Jump to Misc Configuration Form + // + goto MISC_OPTIONS_FORM_ID, + prompt = STRING_TOKEN(STR_MISC_OPTION_FORM_TITLE), + help = STRING_TOKEN(STR_MISC_OPTION_FORM_HELP); +endform; + +form formid = PCIE_DEVICE_OPTIONS_FORM_ID, + + title = STRING_TOKEN(STR_PCIE_OPTIONS_FORM_TITLE); + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + oneof varid = Setup.PcieRootPortSpeed[0], + prompt = STRING_TOKEN (STR_PCIE_SPEED_PROMPT0), + help = STRING_TOKEN (STR_PCIE_SPEED_HELP), + option text = STRING_TOKEN (STR_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN (STR_GEN1), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN (STR_GEN2), value = 2, flags = RESET_REQUIRED; + endoneof; + oneof varid = Setup.PcieRootPortSpeed[1], + prompt = STRING_TOKEN (STR_PCIE_SPEED_PROMPT1), + help = STRING_TOKEN (STR_PCIE_SPEED_HELP), + option text = STRING_TOKEN (STR_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN (STR_GEN1), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN (STR_GEN2), value = 2, flags = RESET_REQUIRED; + endoneof; + oneof varid = Setup.PcieRootPortSpeed[2], + prompt = STRING_TOKEN (STR_PCIE_SPEED_PROMPT2), + help = STRING_TOKEN (STR_PCIE_SPEED_HELP), + option text = STRING_TOKEN (STR_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN (STR_GEN1), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN (STR_GEN2), value = 2, flags = RESET_REQUIRED; + endoneof; + oneof varid = Setup.PcieRootPortSpeed[3], + prompt = STRING_TOKEN (STR_PCIE_SPEED_PROMPT3), + help = STRING_TOKEN (STR_PCIE_SPEED_HELP), + option text = STRING_TOKEN (STR_AUTO), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN (STR_GEN1), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN (STR_GEN2), value = 2, flags = RESET_REQUIRED; + endoneof; + // + //PCIe Port + // + oneof varid = Setup.IchPciExp[0], + prompt = STRING_TOKEN(STR_ICH_PCIERP1_PROMPT), + help = STRING_TOKEN(STR_ICH_PCIERP_HELP), + option text = STRING_TOKEN(STR_ENABLE), value=1, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 | RESET_REQUIRED; + endoneof; + + suppressif ideqval Setup.IchPciExp[0] == 0x0; + oneof varid = Setup.IchPciExp[1], + prompt = STRING_TOKEN(STR_ICH_PCIERP2_PROMPT), + help = STRING_TOKEN(STR_ICH_PCIERP_HELP), + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value=0, flags= DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + suppressif NOT ideqval Setup.IchPciExp[0] == 0x0; + text + help = STRING_TOKEN(STR_ICH_PCIERP_HELP), + text = STRING_TOKEN(STR_ICH_PCIERP2_PROMPT), + text = STRING_TOKEN(STR_ICH_PCIERP_DISABLE_HELP), + flags = 0, + key = 0; + endif; + + suppressif ideqval Setup.IchPciExp[0] == 0x0; + oneof varid = Setup.IchPciExp[2], + prompt = STRING_TOKEN(STR_ICH_PCIERP3_PROMPT), + help = STRING_TOKEN(STR_ICH_PCIERP_HELP), + option text = STRING_TOKEN(STR_ENABLE), value=1, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 | RESET_REQUIRED; + endoneof; + endif; + + suppressif NOT ideqval Setup.IchPciExp[0] == 0x0; + text + help = STRING_TOKEN(STR_ICH_PCIERP_HELP), + text = STRING_TOKEN(STR_ICH_PCIERP3_PROMPT), + text = STRING_TOKEN(STR_ICH_PCIERP_DISABLE_HELP), + flags = 0, + key = 0; + endif; + + suppressif ideqval Setup.IchPciExp[0] == 0x0; + oneof varid = Setup.IchPciExp[3], + prompt = STRING_TOKEN(STR_ICH_PCIERP4_PROMPT), + help = STRING_TOKEN(STR_ICH_PCIERP_HELP), + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value=0, flags= 0 | RESET_REQUIRED; + endoneof; + endif; + + suppressif NOT ideqval Setup.IchPciExp[0] == 0x0; + text + help = STRING_TOKEN(STR_ICH_PCIERP_HELP), + text = STRING_TOKEN(STR_ICH_PCIERP4_PROMPT), + text = STRING_TOKEN(STR_ICH_PCIERP_DISABLE_HELP), + flags = 0, + key = 0; + endif; + + +endform; + +form formid = USB_OPTIONS_FORM_ID, + + title = STRING_TOKEN(STR_USB_OPTIONS_FORM_TITLE); + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + oneof varid = Setup.UsbAutoMode, + questionid = 0x123A, + prompt = STRING_TOKEN(STR_USB_AUTO_MODE_PROMPT), + help = STRING_TOKEN(STR_USB_AUTO_MODE_HELP), + flags = INTERACTIVE, + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + endoneof; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + // + //XHCI support + // + grayoutif ideqval Setup.UsbAutoMode == 0x1; + grayoutif ideqval Setup.PchUsb20 == 0x1; + oneof varid = Setup.UsbXhciSupport, + questionid = 0x123B, + prompt = STRING_TOKEN(STR_USB_XHCI_SUPPORT_PROMPT), + help = STRING_TOKEN(STR_USB_XHCI_SUPPORT_HELP), + flags = INTERACTIVE, + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + endoneof; + + suppressif ideqval Setup.UsbXhciSupport == 0x0; + oneof varid = Setup.Hsic0, + prompt = STRING_TOKEN(STR_USB_HSIC_0_PROMPT), + help = STRING_TOKEN(STR_USB_HSIC_0_HELP), + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + oneof varid = Setup.PchUsb30Mode, + prompt = STRING_TOKEN(STR_PCH_USB30_MODE_PROMPT), + help = STRING_TOKEN(STR_PCH_USB30_MODE_HELP), + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING |RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + endoneof; + + oneof varid = Setup.UsbXhciLpmSupport, + prompt = STRING_TOKEN(STR_USB_XHCI_LPM_SUPPORT_PROMPT), + help = STRING_TOKEN(STR_USB_XHCI_LPM_SUPPORT_HELP), + + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + + endoneof; + endif; + endif; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + oneof varid = Setup.PchUsbOtg, + prompt = STRING_TOKEN(STR_PCH_USB_OTG_PROMPT), + help = STRING_TOKEN(STR_PCH_USB_OTG_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING |RESET_REQUIRED; + option text = STRING_TOKEN(STR_PCI_MODE_STRING), value = 1, flags = RESET_REQUIRED; + endoneof; + + oneof varid = Setup.PchUsbVbusOn, + prompt = STRING_TOKEN(STR_PCH_USB_VBUS_PROMPT), + help = STRING_TOKEN(STR_PCH_USB_VBUS_HELP), + option text = STRING_TOKEN(STR_OFF), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ON), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_AUTO), value = 2, flags = RESET_REQUIRED; + endoneof; + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + // + //EHCI support + // + grayoutif ideqval Setup.UsbAutoMode == 0x1; + grayoutif ideqval Setup.UsbXhciSupport == 0x1; + oneof varid = Setup.PchUsb20, + questionid = 0x123C, + prompt = STRING_TOKEN(STR_PCH_USB21_PROMPT), + help = STRING_TOKEN(STR_PCH_USB2_HELP), + flags = INTERACTIVE, + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value= 0, flags= DEFAULT | MANUFACTURING |RESET_REQUIRED; + endoneof; + + oneof varid = Setup.PchUsbRmh, + prompt = STRING_TOKEN(STR_PCH_USBRMH_PROMPT), + help = STRING_TOKEN(STR_PCH_USBRMH_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.PchEhciDebug, + prompt = STRING_TOKEN(STR_PCH_USB_EHCIDEBUG_PROMPT), + help = STRING_TOKEN(STR_PCH_USB_EHCIDEBUG_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + endoneof; + + suppressif TRUE; + oneof varid = Setup.EhciPllCfgEnable, + prompt = STRING_TOKEN(STR_EHCI_PLL_CFG_PROMPT), + help = STRING_TOKEN(STR_EHCI_PLL_CFG_RTD3_DIS_HELP), + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + endoneof; + endif; + endif; + + // + // Usb ports per-port disable control enable + // + oneof varid = Setup.PchUsbPerPortCtl, + prompt = STRING_TOKEN(STR_PCH_USB_PER_PORT_PROMPT), + help = STRING_TOKEN(STR_PCH_USB_PER_PORT_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + suppressif ideqval Setup.PchUsbPerPortCtl == 0x0; + oneof varid = Setup.PchUsbPort[0], + prompt = STRING_TOKEN(STR_PCH_USB_PORT0_PROMPT), + help = STRING_TOKEN(STR_PCH_USB_PORT_DIS_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.PchUsbPort[1], + prompt = STRING_TOKEN(STR_PCH_USB_PORT1_PROMPT), + help = STRING_TOKEN(STR_PCH_USB_PORT_DIS_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.PchUsbPort[2], + prompt = STRING_TOKEN(STR_PCH_USB_PORT2_PROMPT), + help = STRING_TOKEN(STR_PCH_USB_PORT_DIS_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.PchUsbPort[3], + prompt = STRING_TOKEN(STR_PCH_USB_PORT3_PROMPT), + help = STRING_TOKEN(STR_PCH_USB_PORT_DIS_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + + endif; + +endform; + +// +// SATA Controller +// +form formid = DRIVE_CONFIGURATION_ID, + + title = STRING_TOKEN(STR_IDE_FORM_TITLE); + + // + // Title on Drive Configuration Page + // + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_IDE_FORM_TITLE), + text = STRING_TOKEN(STR_NULL_STRING), + flags = 0, + key = 0; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + subtitle text = STRING_TOKEN(STR_CHIPSET_SATA_STRING); + + oneof varid = Setup.Sata, + prompt = STRING_TOKEN(STR_SATA_PROMPT), + help = STRING_TOKEN(STR_SATA_HELP), + option text = STRING_TOKEN(STR_ENABLE), value=1, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.SataTestMode, + prompt = STRING_TOKEN(STR_SATA_TEST_MODE_PROMPT), + help = STRING_TOKEN(STR_SATA_TEST_MODE_HELP), + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + suppressif ideqval Setup.Sata == 0x00; + oneof varid = Setup.SataType, + prompt = STRING_TOKEN(STR_SATA_TYPE_PROMPT), + help = STRING_TOKEN(STR_SATA_TYPE_HELP1), + option text = STRING_TOKEN(STR_SATA_IDE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_SATA_AHCI), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_SATA0_STRING), + text = STRING_TOKEN(STR_SATA0_NAME), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_SATA1_STRING), + text = STRING_TOKEN(STR_SATA1_NAME), + flags = 0, + key = 0; + + suppressif ideqval Setup.SataType == 0x0; + oneof varid = Setup.Sata0HotPlugCap, + prompt = STRING_TOKEN(STR_SATA0_HOTPLUG_CAP_PROMPT), + help = STRING_TOKEN(STR_SATA_HOTPLUG_CAP_HELP), + option text = STRING_TOKEN(STR_ENABLE), value= 1, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.Sata1HotPlugCap, + prompt = STRING_TOKEN(STR_SATA1_HOTPLUG_CAP_PROMPT), + help = STRING_TOKEN(STR_SATA_HOTPLUG_CAP_HELP), + option text = STRING_TOKEN(STR_ENABLE), value= 1, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 | RESET_REQUIRED; + endoneof; + endif; + + endif; //SATA enable + +endform; + +form formid = LPSS_CONFIGURATION_ID, + + title = STRING_TOKEN(STR_LPSS_SCC_FORM_TITLE); + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + oneof varid = Setup.LpssPciModeEnabled, + prompt = STRING_TOKEN(STR_LPSS_PCI_PROMPT), + help = STRING_TOKEN(STR_LPSS_PCI_HELP), + option text = STRING_TOKEN(STR_ACPI_MODE), value=0, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_PCI_MODE), value=1, flags=0| RESET_REQUIRED; + endoneof; + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + subtitle text = STRING_TOKEN(STR_SCC_SETTING_SUBTITLE); + oneof varid = Setup.eMMCBootMode, + prompt = STRING_TOKEN(STR_EMMC_BOOT_PROMPT), + help = STRING_TOKEN(STR_EMMC_BOOT_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_AUTO_DETECT), value=1, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC_BOOT_41), value=2, flags=0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC_BOOT_45), value=3, flags=0 | RESET_REQUIRED; + endoneof; + + + + oneof varid = Setup.SecureErase, + questionid = 0x1240, + prompt = STRING_TOKEN(STR_SECURE_ERASE_PROMPT), + help = STRING_TOKEN(STR_SECURE_ERASE_HELP), + flags = INTERACTIVE, + option text = STRING_TOKEN(STR_DISABLE), value=0, flags= DEFAULT |MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= RESET_REQUIRED; + endoneof; + + + + subtitle text = STRING_TOKEN(STR_NULL_STRING); +grayoutif NOT ideqval Setup.eMMCBootMode == 0x3; + oneof varid = Setup.LpsseMMC45Enabled, + prompt = STRING_TOKEN(STR_SCC_EMMC45_PROMPT), + help = STRING_TOKEN(STR_SCC_EMMC45_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags=DEFAULT | RESET_REQUIRED; + endoneof; + oneof varid = Setup.LpsseMMC45DDR50Enabled, + prompt = STRING_TOKEN(STR_SCC_EMMC45_DDR50_PROMPT), + help = STRING_TOKEN(STR_SCC_EMMC45_DDR50_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags=DEFAULT | RESET_REQUIRED; + endoneof; + oneof varid = Setup.LpsseMMC45HS200Enabled, + prompt = STRING_TOKEN(STR_SCC_EMMC45_HS200_PROMPT), + help = STRING_TOKEN(STR_SCC_EMMC45_HS200_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags=DEFAULT| RESET_REQUIRED; + endoneof; + + grayoutif ideqval Setup.LpsseMMC45DDR50Enabled == 0x1; + oneof varid = Setup.LpsseMMC45RetuneTimerValue, + prompt = STRING_TOKEN(STR_SCC_EMMC45_RE_TUNE_TIMER_VALUE), + help = STRING_TOKEN(STR_SCC_EMMC45_RE_TUNE_TIMER_VALUE_HELP), + option text = STRING_TOKEN(STR_EMMC45_TIMER_0), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_1), value =1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_2), value =2, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_3), value =3, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_4), value =4, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_5), value =5, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_6), value =6, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_7), value =7, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_8), value =8, flags = MANUFACTURING| DEFAULT|RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_9), value =9, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_10), value =10, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_11), value =11, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_12), value =12, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_13), value =13, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_14), value =14, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_EMMC45_TIMER_15), value =15, flags = RESET_REQUIRED; + endoneof; + endif; // grayoutif ideqval Setup.LpsseMMC45DDR50Enabled == 0x1; + endif; // grayoutif NOT ideqval Setup.eMMCBootMode == 0x1; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + subtitle text = STRING_TOKEN(STR_NULL_STRING); + oneof varid = Setup.LpssSdioEnabled, + prompt = STRING_TOKEN(STR_SCC_SDIO_PROMPT), + help = STRING_TOKEN(STR_SCC_SDIO_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.LpssSdcardEnabled, + prompt = STRING_TOKEN(STR_SCC_SDCARD_PROMPT), + help = STRING_TOKEN(STR_SCC_SDCARD_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= DEFAULT|MANUFACTURING | RESET_REQUIRED; + endoneof; + + +grayoutif NOT ideqval Setup.LpssSdcardEnabled == 0x1; + grayoutif ideqval Setup.LpssSdCardDDR50Enabled == 0x1; + oneof varid = Setup.LpssSdCardSDR25Enabled, + prompt = STRING_TOKEN(STR_SCC_SD_SDR25_PROMPT), + help = STRING_TOKEN(STR_SCC_SD_SDR25_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags=0 | RESET_REQUIRED; + endoneof; + endif; // grayoutif ideqval Setup.LpsseMMC45DDR50Enabled == 0x1; + + grayoutif ideqval Setup.LpssSdCardSDR25Enabled == 0x1; + oneof varid = Setup.LpssSdCardDDR50Enabled, + prompt = STRING_TOKEN(STR_SCC_SD_DDR50_PROMPT), + help = STRING_TOKEN(STR_SCC_SD_DDR50_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags=0 | RESET_REQUIRED; + endoneof; + endif; // grayoutif ideqval Setup.LpssSdCardSDR25Enabled == 0x1; + + oneof varid = Setup.SdCardRemovable, + prompt = STRING_TOKEN(STR_SCC_SDCARD_REMOVABILITY), + help = STRING_TOKEN(STR_SCC_SDCARD_REMOVABILITY_HELP), + option text = STRING_TOKEN(STR_SCC_SDCARD_NON_REMOVABLE), value=0, flags=0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_SCC_SDCARD_REMOVABLE), value=1, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + +endif; // grayoutif NOT ideqval Setup.LpssSdcardEnabled == 0x1; + + + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + subtitle text = STRING_TOKEN(STR_LPSS1_SETTING_SUBTITLE); + + oneof varid = Setup.LpssDma0Enabled, + prompt = STRING_TOKEN(STR_LPSS_DMA1_PROMPT), + help = STRING_TOKEN(STR_LPSS_DMA1_HELP), + flags = INTERACTIVE, + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + grayoutif ideqval Setup.LpssDma0Enabled == 0x00; + oneof varid = Setup.LpssHsuart0Enabled, + prompt = STRING_TOKEN(STR_LPSS_HSUART1_PROMPT), + help = STRING_TOKEN(STR_LPSS_HSUART1_HELP_ENBDT_DEV_LIST), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags= MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= 0 | DEFAULT | RESET_REQUIRED; + endoneof; + endif; + + //Add control flow + grayoutif ideqval Setup.LpssHsuart0Enabled == 0x00; + oneof varid = Setup.LpssHsuart0FlowControlEnabled, + prompt = STRING_TOKEN(STR_LPSS_HSUART1_FLOWCONTROL_PROMPT), + help = STRING_TOKEN(STR_LPSS_HSUART1_HELP_ENBDT_DEV_LIST), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 |DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + grayoutif ideqval Setup.LpssDma0Enabled == 0x00; + oneof varid = Setup.LpssHsuart1Enabled, + prompt = STRING_TOKEN(STR_LPSS_HSUART2_PROMPT), + help = STRING_TOKEN(STR_LPSS_HSUART2_HELP_ENBDT_DEV_LIST), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= 0 | DEFAULT | RESET_REQUIRED; + endoneof; + endif; + + //Add control flow + grayoutif ideqval Setup.LpssHsuart1Enabled == 0x00; + oneof varid = Setup.LpssHsuart1FlowControlEnabled, + prompt = STRING_TOKEN(STR_LPSS_HSUART2_FLOWCONTROL_PROMPT), + help = STRING_TOKEN(STR_LPSS_HSUART1_HELP_ENBDT_DEV_LIST), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 |DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + + grayoutif ideqval Setup.LpssDma0Enabled == 0x00; + oneof varid = Setup.LpssPwm0Enabled, + prompt = STRING_TOKEN(STR_PWM1_PROMPT), + help = STRING_TOKEN(STR_PWM1_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= 0 | DEFAULT | RESET_REQUIRED; + endoneof; + endif; + + grayoutif ideqval Setup.LpssDma0Enabled == 0x00; + oneof varid = Setup.LpssPwm1Enabled, + prompt = STRING_TOKEN(STR_PWM2_PROMPT), + help = STRING_TOKEN(STR_PWM2_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= 0 | DEFAULT | RESET_REQUIRED; + endoneof; + endif; + + grayoutif ideqval Setup.LpssDma0Enabled == 0x00; + oneof varid = Setup.LpssSpiEnabled, + prompt = STRING_TOKEN(STR_LPSS_SPI_PROMPT), + help = STRING_TOKEN(STR_LPSS_SPI_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= 0 |DEFAULT | RESET_REQUIRED; + endoneof; + endif; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + subtitle text = STRING_TOKEN(STR_LPSS2_SETTING_SUBTITLE); + + oneof varid = Setup.LpssDma1Enabled, + prompt = STRING_TOKEN(STR_LPSS_DMA2_PROMPT), + help = STRING_TOKEN(STR_LPSS_DMA2_HELP), + flags = INTERACTIVE, + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 |RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + +/* + grayoutif ideqval Setup.LpssDma1Enabled == 0x00; + oneof varid = Setup.LpssI2C0Enabled, + prompt = STRING_TOKEN(STR_LPSS_I2C1_PROMPT), + help = STRING_TOKEN(STR_LPSS_I2C1_HELP_ENBDT_DEV_LIST), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 |DEFAULT |RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + + grayoutif ideqval Setup.LpssDma1Enabled == 0x00; + oneof varid = Setup.LpssI2C1Enabled, + prompt = STRING_TOKEN(STR_LPSS_I2C2_PROMPT), + help = STRING_TOKEN(STR_LPSS_I2C2_HELP_ENBDT_DEV_LIST), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 |DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + grayoutif ideqval Setup.LpssDma1Enabled == 0x00; + oneof varid = Setup.LpssI2C2Enabled, + prompt = STRING_TOKEN(STR_LPSS_I2C3_PROMPT), + help = STRING_TOKEN(STR_LPSS_I2C3_HELP_ENBDT_DEV_LIST), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 |DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + grayoutif ideqval Setup.LpssDma1Enabled == 0x00; + oneof varid = Setup.LpssI2C3Enabled, + prompt = STRING_TOKEN(STR_LPSS_I2C4_PROMPT), + help = STRING_TOKEN(STR_LPSS_I2C4_HELP_ENBDT_DEV_LIST), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 |DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + grayoutif ideqval Setup.LpssDma1Enabled == 0x00; + oneof varid = Setup.LpssI2C4Enabled, + prompt = STRING_TOKEN(STR_LPSS_I2C5_PROMPT), + help = STRING_TOKEN(STR_LPSS_I2C5_HELP_ENBDT_DEV_LIST), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 |DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; +*/ + grayoutif ideqval Setup.LpssDma1Enabled == 0x00; + oneof varid = Setup.LpssI2C5Enabled, + prompt = STRING_TOKEN(STR_LPSS_I2C6_PROMPT), + help = STRING_TOKEN(STR_LPSS_I2C6_HELP_ENBDT_DEV_LIST), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 |RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= DEFAULT |MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + grayoutif ideqval Setup.LpssDma1Enabled == 0x00; + oneof varid = Setup.LpssI2C6Enabled, + prompt = STRING_TOKEN(STR_LPSS_I2C7_PROMPT), + help = STRING_TOKEN(STR_LPSS_I2C7_HELP_ENBDT_DEV_LIST), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=0 |RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags= DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + subtitle text = STRING_TOKEN(STR_I2C_DEVICE_SETTING_SUBTITLE); + + oneof varid = Setup.I2CTouchAd, + prompt = STRING_TOKEN(STR_I2C_TOUCH_PROMPT), + help = STRING_TOKEN(STR_I2C_TOUCH_HELP), + option text = STRING_TOKEN(STR_AUTO), value=0, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_I2C_FVP), value=0x4B, flags=0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_I2C_FFRD), value=0x4A, flags=0 | RESET_REQUIRED; + endoneof; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + oneof varid = Setup.SAR1, + prompt = STRING_TOKEN(STR_SAR_SENSOR_PROMPT), + help = STRING_TOKEN(STR_SAR_SENSOR_HELP), + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING |RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + endoneof; +endform; + + +// +//LAN Controller +// +form formid = LAN_OPTIONS_FORM_ID, + + title = STRING_TOKEN(STR_LAN_OPTIONS_FORM_TITLE); + + subtitle text = STRING_TOKEN(STR_LAN_OPTIONS_FORM_TITLE); + + oneof varid = Setup.Lan, + prompt = STRING_TOKEN(STR_PCH_LAN_CONTROLLER), + help = STRING_TOKEN(STR_PCH_LAN_CONTROLLER_HELP), + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + suppressif ideqval Setup.Lan == 0; + oneof varid = Setup.WakeOnLanS5, + prompt = STRING_TOKEN(STR_PCH_LAN_WOL_PROMPT), + help = STRING_TOKEN(STR_PCH_LAN_WOL_HELP), + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + endoneof; + + oneof varid = Setup.SlpLanLowDc, + prompt = STRING_TOKEN(STR_PCH_SLP_LAN_LOW_DC_PROMPT), + help = STRING_TOKEN(STR_PCH_SLP_LAN_LOW_DC_HELP), + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + endoneof; + + oneof varid = Setup.BootNetwork, + prompt = STRING_TOKEN(STR_PCH_PXEROM_CONTROL), + help = STRING_TOKEN(STR_PCH_PXEROM_CONTROL_HELP), + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING |RESET_REQUIRED; + endoneof; + endif; + +endform; + +// +// Azalia Configuration +// +form formid = AZALIA_OPTIONS_FORM_ID, + + title = STRING_TOKEN(STR_AZALIA_OPTIONS_FORM_TITLE); + + subtitle text = STRING_TOKEN(STR_AZALIA_OPTIONS_FORM_TITLE); + oneof varid = Setup.Lpe, + prompt = STRING_TOKEN(STR_LPE_PROMPT), + help = STRING_TOKEN(STR_LPE_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_LPE_PCI_MODE), value=1, flags=0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_LPE_ACPI_MODE), value=2, flags=0 | RESET_REQUIRED; + endoneof; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + suppressif ideqval Setup.AzaliaDs == 0x1; + oneof varid = Setup.PchAzalia, + prompt = STRING_TOKEN(STR_PCH_AZALIA_PROMPT), + help = STRING_TOKEN(STR_PCH_AZALIA_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = 0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + suppressif ideqval Setup.AzaliaDs == 0x0; + text + help = STRING_TOKEN(STR_PCH_AZALIA_DS_SUPPORT), + text = STRING_TOKEN(STR_PCH_AZALIA_PROMPT), + text = STRING_TOKEN(STR_ENABLE), + flags = 0, + key = 0; + endif; + + suppressif ideqval Setup.PchAzalia == 0x0; + oneof varid = Setup.AzaliaVCiEnable, + prompt = STRING_TOKEN(STR_AZALIA_VC_PROMPT), + help = STRING_TOKEN(STR_AZALIA_VC_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + suppressif ideqval Setup.PchAzalia == 0x0; + oneof varid = Setup.AzaliaDs, + prompt = STRING_TOKEN(STR_AZALIA_DS_PROMPT), + help = STRING_TOKEN(STR_AZALIA_DS_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + endoneof; + endif; + + suppressif ideqval Setup.PchAzalia == 0x0; + oneof varid = Setup.AzaliaPme, + prompt = STRING_TOKEN(STR_AZALIA_PME_PROMPT), + help = STRING_TOKEN(STR_AZALIA_PME_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.HdmiCodec, + prompt = STRING_TOKEN(STR_HDMI_CODEC_PROMPT), + help = STRING_TOKEN(STR_HDMI_CODEC_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + +endform; + +// +// Misc Configuration +// +form formid = MISC_OPTIONS_FORM_ID, + + title = STRING_TOKEN(STR_MISC_OPTION_FORM_TITLE); + + subtitle text = STRING_TOKEN(STR_MISC_OPTION_FORM_TITLE); + // + // HPET Disable/Enable + // + oneof varid = Setup.Hpet, + prompt = STRING_TOKEN(STR_HPET_PROMPT), + help = STRING_TOKEN(STR_HPET_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0x00, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=0x01, flags=DEFAULT | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.StateAfterG3, + prompt = STRING_TOKEN(STR_STATE_AFTER_G3), + help = STRING_TOKEN(STR_STATE_AFTER_G3_HELP), + option text = STRING_TOKEN(STR_S0_AFTER_G3_STRING), value = 0, flags = DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_S5_AFTER_G3_STRING), value = 1, flags = MANUFACTURING | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.EnableClockSpreadSpec, + prompt = STRING_TOKEN(STR_CLOCK_SPREAD_SPEC_ENABLE), + help = STRING_TOKEN(STR_CLOCK_SPREAD_SPEC_ENABLE_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + endoneof; + + + oneof varid = Setup.UartInterface, + prompt = STRING_TOKEN(STR_PCH_UART_SELECT), + help = STRING_TOKEN(STR_PCH_UART_SELECT_HELP), + option text = STRING_TOKEN(STR_UART_SELECT_PCU), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_UART_SELECT_SIO), value = 1, flags = RESET_REQUIRED; + endoneof; + + suppressif ideqval Setup.LpssHsuart0Enabled == 1 OR ideqval Setup.UartInterface == 1; + oneof varid = Setup.PcuUart1, + prompt = STRING_TOKEN(STR_PCU_UART_A), + help = STRING_TOKEN(STR_PCU_UART_A_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + oneof varid = Setup.SpiRwProtect, + prompt = STRING_TOKEN(STR_PCH_SPI_WP_PROMPT), + help = STRING_TOKEN(STR_PCH_SPI_WP_HELP), + option text = STRING_TOKEN(STR_PCH_SPI_WP_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING |RESET_REQUIRED; + option text = STRING_TOKEN(STR_PCH_SPI_WP_ENABLE), value = 1, flags = RESET_REQUIRED; + endoneof; + + oneof varid = Setup.MmioSize, + prompt = STRING_TOKEN(STR_MMIO_PROMPT), + help = STRING_TOKEN(STR_MMIO_HELP), + option text = STRING_TOKEN(STR_MMIO_0_75G_STRING), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_MMIO_1G_STRING), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_MMIO_1_25G_STRING), value = 2, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_MMIO_1_5G_STRING), value = 3, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_MMIO_2G_STRING), value = 4, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.PcieDynamicGating, + prompt = STRING_TOKEN(STR_PCIEDYNCLK_PROMPT), + help = STRING_TOKEN(STR_PCIEDYNCLK_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING |RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + endoneof; + + oneof varid = Setup.GpioWakeCapability, + prompt = STRING_TOKEN(STR_GPIO_WAKE_CAPABILITY_ENABLE), + help = STRING_TOKEN(STR_GPIO_WAKE_CAPABILITY_ENABLE_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING |RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = RESET_REQUIRED; + endoneof; +endform; diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/SystemComponent.vfi b/Vlv2TbltDevicePkg/PlatformSetupDxe/SystemComponent.vfi new file mode 100644 index 0000000000..e21f8803e3 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/SystemComponent.vfi @@ -0,0 +1,86 @@ +// +// +// Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials are licensed and made available under +// the terms and conditions of the BSD License that accompanies this distribution. +// The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// +// +// +// Module Name: +// +// SystemComponent.vfr +// +// Abstract: +// +// Driver Setup formset. +// +// Revision History: +// ------------------------------------------------------------------------------ +// Rev Date Name Description +// ------------------------------------------------------------------------------ + +// --*/ + +form formid = SYSTEM_COMPONENT_FORM_ID, + + title = STRING_TOKEN(STR_SYSTEM_COMPONENT_TITLE); +/* + oneof varid = Setup.CRIDSettings, + prompt = STRING_TOKEN(STR_CRID_PROMPT), + help = STRING_TOKEN(STR_CRID_SETTING_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = MANUFACTURING | DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_CRID_0_STRING), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_CRID_1_STRING), value = 2, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_CRID_2_STRING), value = 3, flags = RESET_REQUIRED; + endoneof; +*/ + + subtitle text = STRING_TOKEN(STR_PNP_CONFIGURATION_TITLE); + oneof varid = Setup.PnpSettings, + prompt = STRING_TOKEN(STR_PNP_SETTING_PROMPT), + help = STRING_TOKEN(STR_PNP_SETTING_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; +#if (PNP_DEBUG == 1) + option text = STRING_TOKEN(STR_PNP_POWER_STRING), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_PNP_PERFORMANCE_STRING), value = 2, flags = RESET_REQUIRED; +#endif + option text = STRING_TOKEN(STR_PNP_POWER_PERFORMANCE_STRING), value = 3, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_PNP_POWER_PERFORMANCE_STRING_A0), value = 4, flags = 0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_PNP_POWER_PERFORMANCE_STRING_B0), value = 5, flags = 0 | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.CfioPnpSettings, + prompt = STRING_TOKEN(STR_CFIO_PNP_SETTING_PROMPT), + help = STRING_TOKEN(STR_CFIO_PNP_SETTING_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = MANUFACTURING | DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = 0 | RESET_REQUIRED; + endoneof; + oneof varid = Setup.TristateLpc, + prompt = STRING_TOKEN(STR_TRISTATE_LPC_PROMPT), + help = STRING_TOKEN(STR_TRISTATE_LPC_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = MANUFACTURING | DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = 0 | RESET_REQUIRED; + endoneof; + + + + + + + oneof varid = Setup.PchFSAOn, + prompt = STRING_TOKEN(STR_PCH_FSA_PROMPT), + help = STRING_TOKEN(STR_PCH_FSA_HELP), + option text = STRING_TOKEN(STR_OFF), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ON), value = 1, flags = RESET_REQUIRED; + endoneof; + + + +endform; diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/Thermal.vfi b/Vlv2TbltDevicePkg/PlatformSetupDxe/Thermal.vfi new file mode 100644 index 0000000000..a6531f9834 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/Thermal.vfi @@ -0,0 +1,83 @@ +// +// +// Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials are licensed and made available under +// the terms and conditions of the BSD License that accompanies this distribution. +// The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// +// +// +// Module Name: +// +// DPTF.vfr +// +// Abstract: +// +// Driver Setup formset. +// +// Revision History: +// ------------------------------------------------------------------------------ +// Rev Date Name Description +// ------------------------------------------------------------------------------ + +// --*/ + +form formid = THERMAL_FORM_ID, + + title = STRING_TOKEN(STR_THERMAL_TITLE); + + subtitle text = STRING_TOKEN(STR_THERMAL_CONFIGURATION); + + + suppressif TRUE; + numeric varid = Setup.PassiveTc1Value, + prompt = STRING_TOKEN (STR_ACPI_PASSIVE_TC1_VALUE), + help = STRING_TOKEN (STR_ACPI_PASSIVE_TC1_VALUE_HELP), + flags = 0 | RESET_REQUIRED, + minimum = 1, + maximum = 16, + step = 1, + default = 1, + endnumeric; + + numeric varid = Setup.PassiveTc2Value, + prompt = STRING_TOKEN (STR_ACPI_PASSIVE_TC2_VALUE), + help = STRING_TOKEN (STR_ACPI_PASSIVE_TC2_VALUE_HELP), + flags = 0 | RESET_REQUIRED, + minimum = 1, + maximum = 16, + step = 1, + default = 5, + endnumeric; + + numeric varid = Setup.PassiveTspValue, + prompt = STRING_TOKEN (STR_ACPI_PASSIVE_TSP_VALUE), + help = STRING_TOKEN (STR_ACPI_PASSIVE_TSP_VALUE_HELP), + flags = 0 | RESET_REQUIRED, + minimum = 2, + maximum = 50, + step = 2, + default = 50, + endnumeric; + endif; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + oneof varid = Setup.DisableActiveTripPoints, + prompt = STRING_TOKEN(STR_DATP_PROMPT), + help = STRING_TOKEN(STR_DATP_HELP), + option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = RESET_REQUIRED; + endoneof; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + + +endform; diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/UnCore.vfi b/Vlv2TbltDevicePkg/PlatformSetupDxe/UnCore.vfi new file mode 100644 index 0000000000..2184a42ea8 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/UnCore.vfi @@ -0,0 +1,240 @@ +// +// +// Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials are licensed and made available under +// the terms and conditions of the BSD License that accompanies this distribution. +// The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// +// +// +// Module Name: +// +// UncoreConfiguration.vfi +// +// Abstract: +// +// Driver Setup formset. +// + + +// --*/ + +form formid = UNCORE_FORM_ID, + title = STRING_TOKEN(STR_UNCORE_CONFIGURATION_TITLE); + + subtitle text = STRING_TOKEN(STR_GOP_TITLE); + + oneof varid = Setup.GOPEnable, + prompt = STRING_TOKEN(STR_GOP_VBIOS_SWITCH), + help = STRING_TOKEN(STR_GOP_VBIOS_SWITCH_HELP), + option text = STRING_TOKEN(STR_ENABLE), value =1, flags = MANUFACTURING | DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + endoneof; + + oneof varid = Setup.GOPBrightnessLevel, + prompt = STRING_TOKEN(STR_GOP_BRIGHTNESS_LEVEL), + help = STRING_TOKEN(STR_GOP_BRIGHTNESS_LEVEL_HELP), + option text = STRING_TOKEN(STR_GOP_BRIGHT_20), value =2, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_GOP_BRIGHT_40), value =3, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_GOP_BRIGHT_60), value =4, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_GOP_BRIGHT_80), value =5, flags = MANUFACTURING| DEFAULT| RESET_REQUIRED; + option text = STRING_TOKEN(STR_GOP_BRIGHT_100), value =6, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_GOP_BRIGHT_120), value =7, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_GOP_BRIGHT_140), value =8, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_GOP_BRIGHT_160), value =9, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_GOP_BRIGHT_180), value =10, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_GOP_BRIGHT_200), value =11, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_GOP_BRIGHT_220), value =12, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_GOP_BRIGHT_240), value =13, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_GOP_BRIGHT_255), value =14, flags = RESET_REQUIRED; + endoneof; + subtitle text = STRING_TOKEN(STR_NULL_STRING); + subtitle text = STRING_TOKEN(STR_IGD_TITLE); + + suppressif ideqval Setup.PrimaryVideoAdaptor == 0x2; + oneof varid = Setup.Igd, + prompt = STRING_TOKEN (STR_IGD_PROMPT), + help = STRING_TOKEN (STR_IGD_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + endif; + + oneof varid = Setup.PrimaryVideoAdaptor, + prompt = STRING_TOKEN(STR_PRIMARY_DISPLAY), + help = STRING_TOKEN(STR_PRIMARY_DISPLAY_HELP), + option text = STRING_TOKEN(STR_AUTOMATIC), value = 3, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_IGD_STRING), value = 0, flags = DEFAULT |MANUFACTURING |RESET_REQUIRED; + option text = STRING_TOKEN(STR_PCI_STRING), value = 2, flags = RESET_REQUIRED; + endoneof; + + + oneof varid = Setup.PavpMode, + prompt = STRING_TOKEN(STR_PAVC_PROMPT), + help = STRING_TOKEN(STR_PAVC_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_PAVP_LITE_MODE), value = 1, flags = MANUFACTURING | DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_PAVP_SERPENT_MODE), value = 2, flags = RESET_REQUIRED; + endoneof; + + + oneof varid = Setup.GTTSize, + prompt = STRING_TOKEN(STR_GTT_SIZE), + help = STRING_TOKEN(STR_GTT_SIZE_HELP), + option text = STRING_TOKEN(GTT_SIZE_1MB), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(GTT_SIZE_2MB), value = 2, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + endoneof; + + oneof varid = Setup.IgdApertureSize, + prompt = STRING_TOKEN(STR_APERTURE_SIZE), + help = STRING_TOKEN(STR_APERTURE_SIZE_HELP), + option text = STRING_TOKEN(APERTURE_SIZE_128MB), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(APERTURE_SIZE_256MB), value = 2, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(APERTURE_SIZE_512MB), value = 3, flags = RESET_REQUIRED; + endoneof; + + oneof varid = Setup.IgdDvmt50PreAlloc, + prompt = STRING_TOKEN(STR_DVMT50_PRE_ALLOC), + help = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_HELP), +// option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_32M), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_64M), value = 2, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_96M), value = 3, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_128M), value = 4, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_160M), value = 5, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_192M), value = 6, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_224M), value = 7, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_256M), value = 8, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_288M), value = 9, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_320M), value = 10, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_352M), value = 11, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_384M), value = 12, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_416M), value = 13, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_448M), value = 14, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_480M), value = 15, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_PRE_ALLOC_512M), value = 16, flags = RESET_REQUIRED; + endoneof; + + oneof varid = Setup.IgdDvmt50TotalAlloc, + prompt = STRING_TOKEN(STR_DVMT50_DVMT ), + help = STRING_TOKEN(STR_DVMT50_DVMT_HELP), + option text = STRING_TOKEN(STR_DVMT50_ALLOC_128), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_ALLOC_256), value = 2, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DVMT50_ALLOC_MAX), value = 3, flags = RESET_REQUIRED; + endoneof; + + // + //Igd Thermal + // + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + subtitle text = STRING_TOKEN(STR_IGD_LCD_CONTROL); + + oneof varid = Setup.LidStatus, + prompt = STRING_TOKEN(STR_FORCE_LID_STATUS_PROMPT), + help = STRING_TOKEN(STR_FORCE_LID_STATUS_ENBDT_HELP), + option text = STRING_TOKEN(STR_LID_STATUS__OFF_PROMPT), value = 0, flags = 0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_LID_STATUS__ON_PROMPT), value = 1, flags = 0 | RESET_REQUIRED; + option text = STRING_TOKEN(STR_LID_STATUS__AUTO_PROMPT), value = 2, flags = MANUFACTURING| DEFAULT| RESET_REQUIRED; + endoneof; + + oneof varid = Setup.IgdLcdIBia, + prompt = STRING_TOKEN(STR_VIDEO_LCD_IBIA), + help = STRING_TOKEN(STR_VIDEO_LCD_IBIAHLP), + option text = STRING_TOKEN(STR_VIDEO_LCD_IBIAA), value = 0, flags =MANUFACTURING| DEFAULT| RESET_REQUIRED; + option text = STRING_TOKEN(STR_VIDEO_LCD_IBIAD), value = 1, flags = 0| RESET_REQUIRED; + option text = STRING_TOKEN(STR_VIDEO_LCD_IBIAL1), value = 2, flags = 0| RESET_REQUIRED; + option text = STRING_TOKEN(STR_VIDEO_LCD_IBIAL2), value = 3, flags = 0| RESET_REQUIRED; + option text = STRING_TOKEN(STR_VIDEO_LCD_IBIAL3), value = 4, flags = 0| RESET_REQUIRED; + option text = STRING_TOKEN(STR_VIDEO_LCD_IBIAL4), value = 5, flags = 0| RESET_REQUIRED; + option text = STRING_TOKEN(STR_VIDEO_LCD_IBIAL5), value = 6, flags = 0| RESET_REQUIRED; + endoneof; + + oneof varid = Setup.AlsEnable, + prompt = STRING_TOKEN (STR_ACPI_ALS_ENABLE), + help = STRING_TOKEN (STR_ACPI_ALS_ENABLE_HELP), + option text = STRING_TOKEN(STR_DISABLE), value=0, flags=DEFAULT | MANUFACTURING | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ENABLE), value=1, flags=0 | RESET_REQUIRED; + endoneof; + + + oneof varid = Setup.IgdFlatPanel, + prompt = STRING_TOKEN(STR_IGD_FLAT_PANEL_PROMPT), + help = STRING_TOKEN(STR_IGD_FLAT_PANEL_HELP), + option text = STRING_TOKEN(STR_AUTOMATIC), value=0x00, flags=DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_640X480), value=0x01, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_800X600), value=0x02, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_1024X768), value=0x03, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_1280X1024), value=0x04, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_1366X768), value=0x05, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_1680X1050), value=0x06, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_1920X1200), value=0x07, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_1280X800), value=0x08, flags=RESET_REQUIRED; + endoneof; + + oneof varid = Setup.BootDisplayDevice, + prompt = STRING_TOKEN(STR_BOOT_DISPLAY_DEVICE_PROMPT), + help = STRING_TOKEN(STR_BOOT_DISPLAY_DEVICE_HELP), + option text = STRING_TOKEN(STR_AUTOMATIC), value=0x00, flags=DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_VGAPORT), value=0x01, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_HDMIPORTB), value=0x02, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_DPPORTB), value=0x03, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_DPPORTC), value=0x04, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_EDPPORTC), value=0x05, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_DSIPORTA), value=0x06, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_DSIPORTC), value=0x07, flags=RESET_REQUIRED; + + endoneof; + // + //Pannel Scaling + // + oneof varid = Setup.PanelScaling, + prompt = STRING_TOKEN(STR_PANNEL_SCALING_PROMPT), + help = STRING_TOKEN(STR_PANNEL_SCALING_HELP), + option text = STRING_TOKEN(STR_AUTOMATIC), value=0x00, flags=DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_PANNEL_SCALING_STRETCH), value=0x01, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_PANNEL_SCALING_CENTER), value=0x02, flags=RESET_REQUIRED; + endoneof; + + // + //GMCH BLC Control + // + oneof varid = Setup.IgdLcdIGmchBlc, + prompt = STRING_TOKEN(STR_VIDEO_LCD_IGMCHBLC_PROMPT), + help = STRING_TOKEN(STR_VIDEO_LCD_IGMCHBLC_HELP), + option text = STRING_TOKEN(STR_VIDEO_LCD_IGMCHBLC1), value=0x00, flags=DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_VIDEO_LCD_IGMCHBLC2), value=0x01, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_VIDEO_LCD_IGMCHBLC3), value=0x02, flags=RESET_REQUIRED; + option text = STRING_TOKEN(STR_VIDEO_LCD_IGMCHBLC4), value=0x03, flags=RESET_REQUIRED; + endoneof; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + // + //ISP Configuration + // + subtitle text = STRING_TOKEN(STR_ISP_CONFIGURATION_TITLE); + + oneof varid = Setup.ISPEn, + prompt = STRING_TOKEN(STR_ISP_ENABLED), + help = STRING_TOKEN(STR_ISP_ENABLED_HELP), + option text = STRING_TOKEN(STR_ENABLE), value = 1, flags = DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + endoneof; + + grayoutif ideqval Setup.ISPEn == 0; + oneof varid = Setup.ISPDevSel, + prompt = STRING_TOKEN (STR_ISP_PCICONFIGURATION_TITLE), + help = STRING_TOKEN (STR_ISP_PCICONFIGURATION_HELP), + option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ISP_PCICONFIG_B0D2F0_TITLE), value = 1, flags = MANUFACTURING | DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ISP_PCICONFIG_B0D3F0_TITLE), value = 2, flags = RESET_REQUIRED; + endoneof; + endif; + +endform; diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/UqiList.uni b/Vlv2TbltDevicePkg/PlatformSetupDxe/UqiList.uni new file mode 100644 index 0000000000000000000000000000000000000000..7ecc5491b0d6a054668d14277bd243af1a7c021e GIT binary patch literal 65892 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 bLQmWE6Sm1xDW~Xi*Jj=4QNp`d+V1}WxMOWv literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/Vfr.vfr b/Vlv2TbltDevicePkg/PlatformSetupDxe/Vfr.vfr new file mode 100644 index 0000000000..6922ce2c3f --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSetupDxe/Vfr.vfr @@ -0,0 +1,128 @@ +// +// +// +// Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials are licensed and made available under +// the terms and conditions of the BSD License that accompanies this distribution. +// The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// +// +#include "Configuration.h" +#include "PlatformSetupDxeStrDefs.h" +#include "Guid/SetupVariable.h" + +formset + guid = SYSTEM_CONFIGURATION_GUID, + title = STRING_TOKEN(STR_SYSTEM_SETUP_TITLE), + help = STRING_TOKEN(STR_SYSTEM_SETUP_HELP), + class = 1, + subclass = 0, + + + varstore SYSTEM_CONFIGURATION, name = Setup, guid = SYSTEM_CONFIGURATION_GUID; + form formid = ROOT_FORM_ID, + title = STRING_TOKEN(STR_SYSTEM_SETUP_TITLE); + + // + // Jump to 2)Main Form + // + goto ROOT_MAIN_FORM_ID, + prompt = STRING_TOKEN(STR_MAIN_TITLE), + help = STRING_TOKEN(STR_MAIN_HELP); + + // + // Jump to 3)Uncore Configuration Form + // + goto UNCORE_FORM_ID, + prompt = STRING_TOKEN(STR_UNCORE_CONFIGURATION_TITLE), + help = STRING_TOKEN(STR_UNCORE_CONFIGURATION_HELP); + + // + // Jump to 4)South Cluster Configuration Form + // + goto SOUTH_CLUSTER_FORM_ID, + prompt = STRING_TOKEN(STR_SOUTH_CLUSTER_TITLE), + help = STRING_TOKEN(STR_SOUTH_CLUSTER_HELP); + + // Jump to 5)Boot Form + // + goto BOOT_CONFIGURATION_FORM_ID, + prompt = STRING_TOKEN(STR_BOOT_CONFIGURATION_TITLE), + help = STRING_TOKEN(STR_BOOT_CONFIGURATION_HELP); + + // + // Jump to 6)Security Configuration Form + // + goto SECURITY_CONFIGURATION_FORM_ID, + prompt = STRING_TOKEN(STR_SECURITY_CONFIGURATION_TITLE), + help = STRING_TOKEN(STR_SECURITY_CONFIGURATION_HELP); + + // + // Jump to 7)Thermal Form + // + goto THERMAL_FORM_ID, + prompt = STRING_TOKEN(STR_THERMAL_TITLE), + help = STRING_TOKEN(STR_THERMAL_HELP); + + // + // Jump to 8) System Component Form + goto SYSTEM_COMPONENT_FORM_ID, + prompt = STRING_TOKEN(STR_SYSTEM_COMPONENT_TITLE), + help = STRING_TOKEN(STR_SYSTEM_COMPONENT_HELP); + + // + // Jump to 10)Debug Configuration Form + // +#if (BYTI_PF_ENABLE == 0) + goto DEBUG_CONFIGURATION_FORM_ID, + prompt = STRING_TOKEN(STR_DEBUG_CONFIGURATION_TITLE), + help = STRING_TOKEN(STR_DEBUG_CONFIGURATION_HELP); +#endif + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + // + // Commit change and exit + // + text + help = STRING_TOKEN(STR_COMMIT_CHANGE_AND_EXIT_HELP), + text = STRING_TOKEN(STR_COMMIT_CHANGE_AND_EXIT_PROMPT), + text = STRING_TOKEN(STR_COMMIT_CHANGE_AND_EXIT_PROMPT), + flags = INTERACTIVE, + key = 0xF001; + + // + // Discard change and exit + // + text + help = STRING_TOKEN(STR_DISCARD_CHANGE_AND_EXIT_HELP), + text = STRING_TOKEN(STR_DISCARD_CHANGE_AND_EXIT_PROMPT), + text = STRING_TOKEN(STR_DISCARD_CHANGE_AND_EXIT_PROMPT), + flags = INTERACTIVE, + key = 0xF002; + + // + // Load default and exit + // + text + help = STRING_TOKEN(STR_LOAD_DEFAULT_AND_EXIT_HELP), + text = STRING_TOKEN(STR_LOAD_DEFAULT_AND_EXIT_PROMPT), + text = STRING_TOKEN(STR_LOAD_DEFAULT_AND_EXIT_PROMPT), + flags = INTERACTIVE, + key = 0xF003; + endform; + + #include "Main.vfi" + #include "UnCore.vfi" + #include "SouthClusterConfig.vfi" + #include "Boot.vfi" + #include "Security.vfi" + #include "Thermal.vfi" + #include "SystemComponent.vfi" + #include "DebugConfig.vfi" +endformset; diff --git a/Vlv2TbltDevicePkg/PlatformSetupDxe/VfrStrings.uni b/Vlv2TbltDevicePkg/PlatformSetupDxe/VfrStrings.uni new file mode 100644 index 0000000000000000000000000000000000000000..16d78f6aa9753a17560c2b4404186b6245450ac5 GIT binary patch literal 214022 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 + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + Platform.c + +Abstract: + + This is a generic template for a child of the IchSmm driver. + + +--*/ + +#include "SmmPlatform.h" +#include + + +// +// Local variables +// +typedef struct { + UINT8 Device; + UINT8 Function; +} EFI_PCI_BUS_MASTER; + +EFI_PCI_BUS_MASTER mPciBm[] = { + { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4 }, + { PCI_DEVICE_NUMBER_PCH_USB, PCI_FUNCTION_NUMBER_PCH_EHCI } +}; + + +UINT16 mAcpiBaseAddr; +SYSTEM_CONFIGURATION mSystemConfiguration; +EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable; +EFI_GLOBAL_NVS_AREA_PROTOCOL *mGlobalNvsAreaPtr; + +UINT16 mPM1_SaveState16; +UINT32 mGPE_SaveState32; + +BOOLEAN mSetSmmVariableProtocolSmiAllowed = TRUE; + + +// +// Variables. Need to initialize this from Setup +// +BOOLEAN mWakeOnLanS5Variable; +BOOLEAN mWakeOnRtcVariable; +UINT8 mWakeupDay; +UINT8 mWakeupHour; +UINT8 mWakeupMinute; +UINT8 mWakeupSecond; + +// +// Use an enum. 0 is Stay Off, 1 is Last State, 2 is Stay On +// +UINT8 mAcLossVariable; + + +static +UINT8 mTco1Sources[] = { + IchnNmi +}; + +UINTN +DevicePathSize ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +VOID +S4S5ProgClock(); + +EFI_STATUS +InitRuntimeScriptTable ( + IN EFI_SYSTEM_TABLE *SystemTable + ); + +VOID +S5SleepWakeOnRtcCallBack ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext + ); + + +VOID +EnableS5WakeOnRtc(); + +UINT8 +HexToBcd( + UINT8 HexValue + ); + +UINT8 +BcdToHex( + IN UINT8 BcdValue + ); + + +VOID +CpuSmmSxWorkAround( + ); + +/** + Initializes the SMM Handler Driver + + @param ImageHandle + @param SystemTable + + @retval None + +**/ +EFI_STATUS +EFIAPI +InitializePlatformSmm ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT8 Index; + EFI_HANDLE Handle; + EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT PowerButtonContext; + EFI_SMM_POWER_BUTTON_DISPATCH_PROTOCOL *PowerButtonDispatch; + EFI_SMM_ICHN_DISPATCH_CONTEXT IchnContext; + EFI_SMM_ICHN_DISPATCH_PROTOCOL *IchnDispatch; + EFI_SMM_SX_DISPATCH_PROTOCOL *SxDispatch; + EFI_SMM_SX_DISPATCH_CONTEXT EntryDispatchContext; + EFI_SMM_SW_DISPATCH_PROTOCOL *SwDispatch; + EFI_SMM_SW_DISPATCH_CONTEXT SwContext; + UINTN VarSize; + EFI_BOOT_MODE BootMode; + + Handle = NULL; + + // + // Locate the Global NVS Protocol. + // + Status = gBS->LocateProtocol ( + &gEfiGlobalNvsAreaProtocolGuid, + NULL, + (void **)&mGlobalNvsAreaPtr + ); + ASSERT_EFI_ERROR (Status); + + + // + // Get the ACPI Base Address + // + + mAcpiBaseAddr = PchLpcPciCfg16( R_PCH_LPC_ACPI_BASE ) & B_PCH_LPC_ACPI_BASE_BAR; + + VarSize = sizeof(SYSTEM_CONFIGURATION); + Status = SystemTable->RuntimeServices->GetVariable( + L"Setup", + &gEfiSetupVariableGuid, + NULL, + &VarSize, + &mSystemConfiguration + ); + if (!EFI_ERROR(Status)) { + mAcLossVariable = mSystemConfiguration.StateAfterG3; + + // + // If LAN is disabled, WOL function should be disabled too. + // + if (mSystemConfiguration.Lan == 0x01){ + mWakeOnLanS5Variable = mSystemConfiguration.WakeOnLanS5; + } else { + mWakeOnLanS5Variable = FALSE; + } + + mWakeOnRtcVariable = mSystemConfiguration.WakeOnRtcS5; + } + + BootMode = GetBootModeHob (); + + // + // Get the Power Button protocol + // + Status = gBS->LocateProtocol( + &gEfiSmmPowerButtonDispatchProtocolGuid, + NULL, + (void **)&PowerButtonDispatch + ); + ASSERT_EFI_ERROR(Status); + + if (BootMode != BOOT_ON_FLASH_UPDATE) { + // + // Register for the power button event + // + PowerButtonContext.Phase = PowerButtonEntry; + Status = PowerButtonDispatch->Register( + PowerButtonDispatch, + PowerButtonCallback, + &PowerButtonContext, + &Handle + ); + ASSERT_EFI_ERROR(Status); + } + // + // Get the Sx dispatch protocol + // + Status = gBS->LocateProtocol ( + &gEfiSmmSxDispatchProtocolGuid, + NULL, + (void **)&SxDispatch + ); + ASSERT_EFI_ERROR(Status); + + // + // Register entry phase call back function + // + EntryDispatchContext.Type = SxS3; + EntryDispatchContext.Phase = SxEntry; + + Status = SxDispatch->Register ( + SxDispatch, + (EFI_SMM_SX_DISPATCH)SxSleepEntryCallBack, + &EntryDispatchContext, + &Handle + ); + + + EntryDispatchContext.Type = SxS4; + + Status = SxDispatch->Register ( + SxDispatch, + S4S5CallBack, + &EntryDispatchContext, + &Handle + ); + ASSERT_EFI_ERROR(Status); + + + EntryDispatchContext.Type = SxS5; + + Status = SxDispatch->Register ( + SxDispatch, + S4S5CallBack, + &EntryDispatchContext, + &Handle + ); + ASSERT_EFI_ERROR(Status); + + Status = SxDispatch->Register ( + SxDispatch, + S5SleepAcLossCallBack, + &EntryDispatchContext, + &Handle + ); + ASSERT_EFI_ERROR(Status); + + // + // Get the Sw dispatch protocol + // + Status = gBS->LocateProtocol ( + &gEfiSmmSwDispatchProtocolGuid, + NULL, + (void **)&SwDispatch + ); + ASSERT_EFI_ERROR(Status); + + // + // Register ACPI enable handler + // + SwContext.SwSmiInputValue = ACPI_ENABLE; + Status = SwDispatch->Register ( + SwDispatch, + EnableAcpiCallback, + &SwContext, + &Handle + ); + ASSERT_EFI_ERROR(Status); + + // + // Register ACPI disable handler + // + SwContext.SwSmiInputValue = ACPI_DISABLE; + Status = SwDispatch->Register ( + SwDispatch, + DisableAcpiCallback, + &SwContext, + &Handle + ); + ASSERT_EFI_ERROR(Status); + + + // + // Register for SmmReadyToBootCallback + // + SwContext.SwSmiInputValue = SMI_SET_SMMVARIABLE_PROTOCOL; + Status = SwDispatch->Register( + SwDispatch, + SmmReadyToBootCallback, + &SwContext, + &Handle + ); + ASSERT_EFI_ERROR(Status); + + // + // Get the ICHn protocol + // + Status = gBS->LocateProtocol( + &gEfiSmmIchnDispatchProtocolGuid, + NULL, + (void **)&IchnDispatch + ); + ASSERT_EFI_ERROR(Status); + + // + // Register for the events that may happen that we do not care. + // This is true for SMI related to TCO since TCO is enabled by BIOS WP + // + for (Index = 0; Index < sizeof(mTco1Sources)/sizeof(UINT8); Index++) { + IchnContext.Type = mTco1Sources[Index]; + Status = IchnDispatch->Register( + IchnDispatch, + (EFI_SMM_ICHN_DISPATCH)DummyTco1Callback, + &IchnContext, + &Handle + ); + ASSERT_EFI_ERROR( Status ); + } + + // + // Lock TCO_EN bit. + // + IoWrite16( mAcpiBaseAddr + R_PCH_TCO_CNT, IoRead16( mAcpiBaseAddr + R_PCH_TCO_CNT ) | B_PCH_TCO_CNT_LOCK ); + + // + // Set to power on from G3 dependent on WOL instead of AC Loss variable in order to support WOL from G3 feature. + // + // + // Set wake from G3 dependent on AC Loss variable and Wake On LAN variable. + // This is because no matter how, if WOL enabled or AC Loss variable not disabled, the board needs to wake from G3 to program the LAN WOL settings. + // This needs to be done after LAN enable/disable so that the PWR_FLR state clear not impacted the WOL from G3 feature. + // + if (mAcLossVariable != 0x00) { + SetAfterG3On (TRUE); + } else { + SetAfterG3On (FALSE); + } + + + + + return EFI_SUCCESS; +} + +VOID +EFIAPI +SmmReadyToBootCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ) +{ + EFI_STATUS Status; + + if (mSetSmmVariableProtocolSmiAllowed) + { + // + // It is okay to use gBS->LocateProtocol here because + // we are still in trusted execution. + // + Status = gBS->LocateProtocol( + &gEfiSmmVariableProtocolGuid, + NULL, + (void **)&mSmmVariable + ); + + ASSERT_EFI_ERROR(Status); + + // + // mSetSmmVariableProtocolSmiAllowed will prevent this function from + // being executed more than 1 time. + // + mSetSmmVariableProtocolSmiAllowed = FALSE; + } + +} + +/** + + @param DispatchHandle The handle of this callback, obtained when registering + @param DispatchContext The predefined context which contained sleep type and phase + + + @retval EFI_SUCCESS Operation successfully performed + +**/ +EFI_STATUS +EFIAPI +SxSleepEntryCallBack ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext + ) +{ + EFI_STATUS Status; + + Status = SaveRuntimeScriptTable (); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Workaround for S3 wake hang if C State is enabled + // + CpuSmmSxWorkAround(); + + return EFI_SUCCESS; +} + +VOID +CpuSmmSxWorkAround( + ) +{ + UINT64 MsrValue; + + MsrValue = AsmReadMsr64 (0xE2); + + if (MsrValue & BIT15) { + return; + } + + if (MsrValue & BIT10) { + MsrValue &= ~BIT10; + AsmWriteMsr64 (0xE2, MsrValue); + } +} + +VOID +ClearP2PBusMaster( + ) +{ + UINT8 Command; + UINT8 Index; + + for (Index = 0; Index < sizeof(mPciBm)/sizeof(EFI_PCI_BUS_MASTER); Index++) { + Command = MmioRead8 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + mPciBm[Index].Device, + mPciBm[Index].Function, + PCI_COMMAND_OFFSET + ) + ); + Command &= ~EFI_PCI_COMMAND_BUS_MASTER; + MmioWrite8 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + mPciBm[Index].Device, + mPciBm[Index].Function, + PCI_COMMAND_OFFSET + ), + Command + ); + } +} + +/** + + Set the AC Loss to turn on or off. + +**/ +VOID +SetAfterG3On ( + BOOLEAN Enable + ) +{ + UINT8 PmCon1; + + // + // ICH handling portion + // + PmCon1 = MmioRead8 ( PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1 ); + PmCon1 &= ~B_PCH_PMC_GEN_PMCON_AFTERG3_EN; + if (Enable) { + PmCon1 |= B_PCH_PMC_GEN_PMCON_AFTERG3_EN; + } + MmioWrite8 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, PmCon1); + +} + +/** + When a power button event happens, it shuts off the machine + +**/ +VOID +EFIAPI +PowerButtonCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT *DispatchContext + ) +{ + // + // Check what the state to return to after AC Loss. If Last State, then + // set it to Off. + // + UINT16 data16; + + if (mWakeOnRtcVariable) { + EnableS5WakeOnRtc(); + } + + if (mAcLossVariable == 1) { + SetAfterG3On (TRUE); + } + + ClearP2PBusMaster(); + + // + // Program clock chip + // + S4S5ProgClock(); + + + data16 = (UINT16)(IoRead16(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN)); + data16 &= B_PCH_ACPI_GPE0a_EN_PCI_EXP; + + + // + // Clear Sleep SMI Status + // + IoWrite16 (mAcpiBaseAddr + R_PCH_SMI_STS, + (UINT16)(IoRead16 (mAcpiBaseAddr + R_PCH_SMI_STS) | B_PCH_SMI_STS_ON_SLP_EN)); + // + // Clear Sleep Type Enable + // + IoWrite16 (mAcpiBaseAddr + R_PCH_SMI_EN, + (UINT16)(IoRead16 (mAcpiBaseAddr + R_PCH_SMI_EN) & (~B_PCH_SMI_EN_ON_SLP_EN))); + + // + // Clear Power Button Status + // + IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_PWRBTN); + + // + // Shut it off now! + // + IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, V_PCH_ACPI_PM1_CNT_S5); + IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, B_PCH_ACPI_PM1_CNT_SLP_EN | V_PCH_ACPI_PM1_CNT_S5); + + // + // Should not return + // + CpuDeadLoop(); +} + + +/** + @param DispatchHandle - The handle of this callback, obtained when registering + + @param DispatchContext - The predefined context which contained sleep type and phase + +**/ +VOID +EFIAPI +S5SleepAcLossCallBack ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext + ) +{ + // + // Check what the state to return to after AC Loss. If Last State, then + // set it to Off. + // + if (mAcLossVariable == 1) { + SetAfterG3On (TRUE); + } +} + +/** + + @param DispatchHandle The handle of this callback, obtained when registering + @param DispatchContext The predefined context which contained sleep type and phase + + @retval Clears the Save State bit in the clock. + +**/ +VOID +EFIAPI +S4S5CallBack ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext + ) +{ + + UINT32 Data32; + + // + // Enable/Disable USB Charging + // + if (mSystemConfiguration.UsbCharging == 0x01) { + Data32 = IoRead32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL); + Data32 |= BIT8; + IoWrite32(GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL, Data32); + } + +} + + +VOID +S4S5ProgClock() +{ +} + +/** + 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 5.0 Section 4.8.2.4 "Real Time Clock Alarm") + + Enable SCI + + @param DispatchHandle - EFI Handle + @param DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT + + @retval Nothing + +**/ +VOID +EFIAPI +EnableAcpiCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ) +{ + UINT32 SmiEn; + UINT16 Pm1Cnt; + UINT16 wordValue; + UINT32 RegData32; + + // + // Disable SW SMI Timer + // + SmiEn = IoRead32(mAcpiBaseAddr + R_PCH_SMI_EN); + SmiEn &= ~B_PCH_SMI_STS_SWSMI_TMR; + IoWrite32(mAcpiBaseAddr + R_PCH_SMI_EN, SmiEn); + + wordValue = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_STS); + if(wordValue & B_PCH_ACPI_PM1_STS_WAK) { + IoWrite32((mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN), 0x0000); + IoWrite32((mAcpiBaseAddr + R_PCH_ACPI_GPE0a_STS), 0xffffffff); + } + else { + mPM1_SaveState16 = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_EN); + + // + // Disable PM sources except power button + // + // power button is enabled only for PCAT. Disabled it on Tablet platform + // + IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_EN, B_PCH_ACPI_PM1_EN_PWRBTN); + IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, 0xffff); + + mGPE_SaveState32 = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN); + IoWrite32(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN, 0x0000); + IoWrite32(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_STS, 0xffffffff); + + } + + // + // Guarantee day-of-month alarm is invalid (ACPI 5.0 Section 4.8.2.4 "Real Time Clock Alarm") + // Clear Status D reg VM bit, Date of month Alarm to make Data in CMOS RAM is no longer Valid + // + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_D); + IoWrite8 (PCAT_RTC_DATA_REGISTER, 0x0); + + + RegData32 = IoRead32(ACPI_BASE_ADDRESS + R_PCH_ALT_GP_SMI_EN); + RegData32 &= ~(BIT7); + IoWrite32((ACPI_BASE_ADDRESS + R_PCH_ALT_GP_SMI_EN), RegData32); + + + // + // Enable SCI + // + Pm1Cnt = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT); + Pm1Cnt |= B_PCH_ACPI_PM1_CNT_SCI_EN; + IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, Pm1Cnt); + + +} + +/** + 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 + + @param DispatchHandle - EFI Handle + @param DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT + + @retval Nothing + +**/ +VOID +EFIAPI +DisableAcpiCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ) +{ + UINT16 Pm1Cnt; + + IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, 0xffff); + IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_EN, mPM1_SaveState16); + + IoWrite32(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_STS, 0xffffffff); + IoWrite32(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN, mGPE_SaveState32); + + // + // Disable SCI + // + Pm1Cnt = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT); + Pm1Cnt &= ~B_PCH_ACPI_PM1_CNT_SCI_EN; + IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, Pm1Cnt); + +} + +/** + When an unknown event happen. + + @retval None + +**/ +VOID +DummyTco1Callback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_ICHN_DISPATCH_CONTEXT *DispatchContext + ) +{ +} + +UINTN +DevicePathSize ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + 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); +} + +/** + + @param DispatchHandle The handle of this callback, obtained when registering + @param DispatchContext The predefined context which contained sleep type and phase + +**/ +VOID +S5SleepWakeOnRtcCallBack ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext + ) +{ + EnableS5WakeOnRtc(); +} + +/** + + @retval 1. Check Alarm interrupt is not set. + 2. Clear Alarm interrupt. + 2. Set RTC wake up date and time. + 2. Enable RTC wake up alarm. + 3. Enable ICH PM1 EN Bit 10(RTC_EN) + +**/ +VOID +EnableS5WakeOnRtc() +{ + UINT8 CmosData; + UINTN i; + EFI_STATUS Status; + UINTN VarSize; + + // + // make sure EFI_SMM_VARIABLE_PROTOCOL is available + // + if (!mSmmVariable) { + return; + } + + VarSize = sizeof(SYSTEM_CONFIGURATION); + + // + // read the variable into the buffer + // + Status = mSmmVariable->SmmGetVariable( + L"Setup", + &gEfiSetupVariableGuid, + NULL, + &VarSize, + &mSystemConfiguration + ); + if (EFI_ERROR(Status) || (!mSystemConfiguration.WakeOnRtcS5)) { + return; + } + mWakeupDay = HexToBcd((UINT8)mSystemConfiguration.RTCWakeupDate); + mWakeupHour = HexToBcd((UINT8)mSystemConfiguration.RTCWakeupTimeHour); + mWakeupMinute = HexToBcd((UINT8)mSystemConfiguration.RTCWakeupTimeMinute); + mWakeupSecond = HexToBcd((UINT8)mSystemConfiguration.RTCWakeupTimeSecond); + + // + // Check RTC alarm interrupt is enabled. If enabled, someone already + // grabbed RTC alarm. Just return. + // + IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B); + if(IoRead8(PCAT_RTC_DATA_REGISTER) & B_RTC_ALARM_INT_ENABLE){ + return; + } + + // + // Set Date + // + IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_D); + CmosData = IoRead8(PCAT_RTC_DATA_REGISTER); + CmosData &= ~(B_RTC_DATE_ALARM_MASK); + CmosData |= mWakeupDay ; + for(i = 0 ; i < 0xffff ; i++){ + IoWrite8(PCAT_RTC_DATA_REGISTER, CmosData); + SmmStall(1); + if(((CmosData = IoRead8(PCAT_RTC_DATA_REGISTER)) & B_RTC_DATE_ALARM_MASK) + == mWakeupDay){ + break; + } + } + + // + // Set Second + // + IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECOND_ALARM); + for(i = 0 ; i < 0xffff ; i++){ + IoWrite8(PCAT_RTC_DATA_REGISTER, mWakeupSecond); + SmmStall(1); + if(IoRead8(PCAT_RTC_DATA_REGISTER) == mWakeupSecond){ + break; + } + } + + // + // Set Minute + // + IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTE_ALARM); + for(i = 0 ; i < 0xffff ; i++){ + IoWrite8(PCAT_RTC_DATA_REGISTER, mWakeupMinute); + SmmStall(1); + if(IoRead8(PCAT_RTC_DATA_REGISTER) == mWakeupMinute){ + break; + } + } + + // + // Set Hour + // + IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOUR_ALARM); + for(i = 0 ; i < 0xffff ; i++){ + IoWrite8(PCAT_RTC_DATA_REGISTER, mWakeupHour); + SmmStall(1); + if(IoRead8(PCAT_RTC_DATA_REGISTER) == mWakeupHour){ + break; + } + } + + // + // Wait for UIP to arm RTC alarm + // + IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A); + while (IoRead8(PCAT_RTC_DATA_REGISTER) & 0x80); + + // + // Read RTC register 0C to clear pending RTC interrupts + // + IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_C); + IoRead8(PCAT_RTC_DATA_REGISTER); + + // + // Enable RTC Alarm Interrupt + // + IoWrite8(PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B); + IoWrite8(PCAT_RTC_DATA_REGISTER, IoRead8(PCAT_RTC_DATA_REGISTER) | B_RTC_ALARM_INT_ENABLE); + + // + // Clear ICH RTC Status + // + IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_RTC); + + // + // Enable ICH RTC event + // + IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_EN, + (UINT16)(IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_EN) | B_PCH_ACPI_PM1_EN_RTC)); +} + +UINT8 +HexToBcd( + IN UINT8 HexValue + ) +{ + UINTN HighByte; + UINTN LowByte; + + HighByte = (UINTN)HexValue / 10; + LowByte = (UINTN)HexValue % 10; + + return ((UINT8)(LowByte + (HighByte << 4))); +} + +UINT8 +BcdToHex( + IN UINT8 BcdValue + ) +{ + UINTN HighByte; + UINTN LowByte; + + HighByte = (UINTN)((BcdValue >> 4) * 10); + LowByte = (UINTN)(BcdValue & 0x0F); + + return ((UINT8)(LowByte + HighByte)); +} + diff --git a/Vlv2TbltDevicePkg/PlatformSmm/PlatformSmm.inf b/Vlv2TbltDevicePkg/PlatformSmm/PlatformSmm.inf new file mode 100644 index 0000000000..69e0a5d990 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSmm/PlatformSmm.inf @@ -0,0 +1,98 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# Module Name: +# +# Platform.inf +# +# Abstract: +# +# Component description file for SMM Platform handler module +# +#--*/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformSmm + FILE_GUID = 99C20A37-042A-46e2-80F4-E4027FDBC86F + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializePlatformSmm + PI_SPECIFICATION_VERSION = 0x0001000A + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + S3Save.c + Platform.c + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + DebugLib + IoLib + BaseLib + BaseMemoryLib + DevicePathLib + HobLib + S3BootScriptLib + StallSmmLib + PchPlatformLib + +[Guids] + gEfiSetupVariableGuid + gDmiDataGuid + gEfiAcpiVariableCompatiblityGuid + gEfiPciLanInfoGuid + gEfiPciLanInfoGuid + +[FeaturePcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode + +[Protocols] + gEfiSmmBaseProtocolGuid + gEfiSmmIchnDispatchProtocolGuid + gEfiGlobalNvsAreaProtocolGuid + gEfiSmmSwDispatchProtocolGuid + gEfiSmmPowerButtonDispatchProtocolGuid + gEfiSmmSxDispatchProtocolGuid + gEfiSmmVariableProtocolGuid + gEfiCpuIo2ProtocolGuid + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[Pcd.common] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + +[Depex] + gEfiSmmBaseProtocolGuid AND + gEfiSmmAccess2ProtocolGuid AND + gEfiSmmPowerButtonDispatchProtocolGuid AND + gEfiSmmSxDispatchProtocolGuid AND + gEfiSmmIchnDispatchProtocolGuid AND + gEfiSmmSwDispatchProtocolGuid AND + gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid AND + gEfiGlobalNvsAreaProtocolGuid + diff --git a/Vlv2TbltDevicePkg/PlatformSmm/S3Save.c b/Vlv2TbltDevicePkg/PlatformSmm/S3Save.c new file mode 100644 index 0000000000..8c7112bf0b --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSmm/S3Save.c @@ -0,0 +1,382 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + IchS3Save.c + +Abstract: + + SMM S3 handler Driver implementation file + +Revision History + +**/ +#include "SmmPlatform.h" + +extern UINT16 mAcpiBaseAddr; +EFI_PHYSICAL_ADDRESS mRuntimeScriptTableBase; + +EFI_STATUS +InitRuntimeScriptTable ( + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT32 VarAttrib; + UINTN VarSize; + ACPI_VARIABLE_SET_COMPATIBILITY *AcpiVariableBase; + + // + // Allocate runtime ACPI script table space. We need it to save some + // settings done by CSM, which runs after normal script table closed + // + Status = gBS->AllocatePages ( + AllocateAnyPages, + EfiACPIReclaimMemory, + 1, + &mRuntimeScriptTableBase + ); + 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 = mRuntimeScriptTableBase; + + return EFI_SUCCESS; +} + +EFI_STATUS +SaveRuntimeScriptTable ( + VOID + ) +{ + SMM_PCI_IO_ADDRESS PciAddress; + UINT32 Data32; + UINT16 Data16; + UINT8 Data8; + UINT8 Mask; + UINTN Index; + UINTN Offset; + UINT8 RegTable[] = { + + // + //Bus , Dev, Func, DMI + // + 0x00 , 0x00, 0x00, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x00 , 0x08, 0x00, 0x00, 0x30, 0x00, 0x00, 0xa0, + + // + //Bus , Dev, Func, LPC device + // + 0x00 , 0x1F, 0x00, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x00 , 0x08, 0x00, 0x07, 0x00, 0x00, 0x90, 0x00, + + // + //Bus , Dev, Func, PCIE device + // + 0x00 , 0x1C, 0x00, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0xC0 , 0x83, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + + // + //Bus , Dev, Func, PCIE device + // + 0x00 , 0x1C, 0x00, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x03 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // + //Bus , Dev, Func, SATA device + // + 0x00 , 0x13, 0x00, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0xf4 , 0xab, 0x27, 0x10, 0xf1, 0x1d, 0x00, 0x40, + + // + //Bus , Dev, Func, EHCI device + // + 0x00 , 0x1D, 0x00, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x10 , 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + + // + //Bus , Dev, Func, SMBUS device + // + 0x00 , 0x1f, 0x03, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x10 , 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // + //Bus , Dev, Func, SMBUS device + // + 0x00 , 0x1f, 0x03, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x02 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // + //Bus , Dev, Func, VGA bus1 + // + 0x01 , 0x00, 0x00, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x58 , 0x81, 0x18, 0x01, 0xb0, 0x00, 0x00, 0x00, + + // + //Bus , Dev, Func, VGA bus1 + // + 0x01 , 0x00, 0x00, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x02 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // + //Bus , Dev, Func, VGA bus1 function 1 + // + 0x01 , 0x00, 0x01, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x51 , 0x80, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, + + // + //Bus , Dev, Func, VGA bus1 function 1 + // + 0x01 , 0x00, 0x01, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x02 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // + //Bus , Dev, Func, IGD bus0 function 0 + // + 0x00 , 0x02, 0x00, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x42 , 0x81, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + + // + //Bus , Dev, Func, USB bus0 function 0 + // + 0x00 , 0x16, 0x00, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x32 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // + //Bus , Dev, Func, HD Audio bus0 function 0 + // + 0x00 , 0x1B, 0x00, + + // + //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF + // + 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + + // + //0xFF indicates the end of the table + // + 0xFF + }; + + // + // These registers have to set in byte order + // + UINT8 ExtReg[] = { 0x9E, 0x9D }; // SMRAM settings + + + + // + // 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 + // + PciAddress.Bus = 0; + PciAddress.Device = 0; + PciAddress.Function = 0; + PciAddress.ExtendedRegister = 0; + + for (Index = 0; Index < 2; Index++) { + // + // Read SRAM setting from Pci(0, 0, 0) + // + PciAddress.Register = ExtReg[Index]; + Data8 = MmioRead8 ( + MmPciAddress (0, + PciAddress.Bus, + PciAddress.Device, + PciAddress.Function, + PciAddress.Register + ) + ); + + // + // Save latest settings to runtime script table + // + S3BootScriptSavePciCfgWrite( + S3BootScriptWidthUint8, + *(UINT64*)&PciAddress, + 1, + &Data8 + ); + } + + + // + // 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 (RegTable[Index] != 0xFF) { + + PciAddress.Bus = RegTable[Index++]; + PciAddress.Device = RegTable[Index++]; + PciAddress.Function = RegTable[Index++]; + PciAddress.Register = 0; + PciAddress.ExtendedRegister = 0; + + Data16 = MmioRead16 ( + MmPciAddress (0, + 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 (RegTable[Index + Offset/32] & Mask ) { + + PciAddress.Register = (UINT8)Offset; + Data32 = MmioRead32 (MmPciAddress (0, PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)); + + // + // Save latest settings to runtime script table + // + S3BootScriptSavePciCfgWrite ( + S3BootScriptWidthUint32, + *(UINT64*)&PciAddress, + 1, + &Data32 + ); + } + } + + Index += 8; + + } + + + // + // Save I/O ports to S3 script table + // + + // + // Selftest KBC + // + Data8 = 0xAA; + S3BootScriptSaveIoWrite ( + S3BootScriptWidthUint8, + 0x64, + (UINTN)1, + &Data8 + ); + + Data32 = IoRead32(mAcpiBaseAddr + R_PCH_SMI_EN); + + S3BootScriptSaveIoWrite ( + S3BootScriptWidthUint32, + (mAcpiBaseAddr + R_PCH_SMI_EN), + 1, + &Data32 + ); + + // + // Save B_ICH_TCO_CNT_LOCK so it will be done on S3 resume path. + // + Data16 = IoRead16(mAcpiBaseAddr + R_PCH_TCO_CNT); + + S3BootScriptSaveIoWrite ( + S3BootScriptWidthUint16, + mAcpiBaseAddr + R_PCH_TCO_CNT, + 1, + &Data16 + ); + + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/PlatformSmm/SmmPlatform.h b/Vlv2TbltDevicePkg/PlatformSmm/SmmPlatform.h new file mode 100644 index 0000000000..0bf76dd37a --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSmm/SmmPlatform.h @@ -0,0 +1,245 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + SmmPlatform.h + +Abstract: + + Header file for + +++*/ + +#ifndef _PLATFORM_H +#define _PLATFORM_H + +#include + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Protocol/GlobalNvsArea.h" +#include +#include +#include +#include +#include + +#include "PchAccess.h" +#include "PlatformBaseAddresses.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT32 ExtendedRegister; +} SMM_PCI_IO_ADDRESS; + +typedef struct { + CHAR8 BoardAaNumber[7]; + UINTN BoardFabNumber; +} BOARD_AA_NUMBER_DECODE; + +// +// BugBug -- Need to get these two values from acpi.h, but right now, they are +// declared in platform-specific variants of this file, so no easy +// way to pick-up the include file and work across platforms. +// Need these definitions to go into a file like common\acpi.h. +// +#define ACPI_ENABLE 0xA0 +#define ACPI_DISABLE 0xA1 + +#define APM_12_FUNCS 0x50 +#define SMI_SET_SMMVARIABLE_PROTOCOL 0x51 // this is used in Cpu\Pentium\Smm\Base\SmmBase.c + +#define SMI_CMD_GET_MSEG_STATUS 0x70 +#define SMI_CMD_UPDATE_MSEG_SIZE 0x71 +#define SMI_CMD_LOAD_STM 0x72 +#define SMI_CMD_UNLOAD_STM 0x73 +#define SMI_CMD_GET_SMRAM_RANGES 0x74 + + +#define PCAT_RTC_ADDRESS_REGISTER 0x74 +#define PCAT_RTC_DATA_REGISTER 0x75 + +#define RTC_ADDRESS_SECOND 0x00 +#define RTC_ADDRESS_SECOND_ALARM 0x01 +#define RTC_ADDRESS_MINUTE 0x02 +#define RTC_ADDRESS_MINUTE_ALARM 0x03 +#define RTC_ADDRESS_HOUR 0x04 +#define RTC_ADDRESS_HOUR_ALARM 0x05 + +#define RTC_ADDRESS_REGISTER_A 0x0A +#define RTC_ADDRESS_REGISTER_B 0x0B +#define RTC_ADDRESS_REGISTER_C 0x0C +#define RTC_ADDRESS_REGISTER_D 0x0D + +#define B_RTC_ALARM_INT_ENABLE 0x20 +#define B_RTC_ALARM_INT_STATUS 0x20 + +#define B_RTC_DATE_ALARM_MASK 0x3F + +#define PCAT_CMOS_2_ADDRESS_REGISTER 0x72 +#define PCAT_CMOS_2_DATA_REGISTER 0x73 + +#define EC_C_PORT 0x66 +#define SMC_SMI_DISABLE 0xBC +#define SMC_ENABLE_ACPI_MODE 0xAA // Enable ACPI mode + +#define IO_MISC 156 + + +#define MAXIMUM_NUMBER_OF_PSTATES 12 +#define ICH_SMM_DATA_PORT 0xB3 + +#define EFI_IA32_PMG_CST_CONFIG 0x000000E2 +#define B_EFI_CST_CONTROL_LOCK BIT15 +#define B_EFI_IO_MWAIT_REDIRECTION_ENABLE BIT10 +#define EFI_IA32_PMG_IO_CAPTURE_ADDR 0x000000E4 + +extern EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *mPciRootBridgeIo; + +// +// Callback function prototypes +// +VOID +EFIAPI +PowerButtonCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT *DispatchContext + ); + +VOID +S5SleepWakeOnLanCallBack ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext + ); + +VOID +EFIAPI +S5SleepAcLossCallBack ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext + ); + + +VOID +EFIAPI +S4S5CallBack ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext + ); + +VOID +EFIAPI +EnableAcpiCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ); + +VOID +EFIAPI +DisableAcpiCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ); + +VOID +EFIAPI +SmmReadyToBootCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ); + +VOID +DummyTco1Callback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_ICHN_DISPATCH_CONTEXT *DispatchContext + ); + + +VOID +PerrSerrCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_ICHN_DISPATCH_CONTEXT *DispatchContext + ); + +VOID +RiCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_ICHN_DISPATCH_CONTEXT *DispatchContext + ); + + +VOID +SetAfterG3On ( + BOOLEAN Enable + ); + +VOID +TurnOffVregUsb ( + ); + +VOID +PStateSupportCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ); + +VOID +PStateTransitionCallback ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ); + +EFI_STATUS +EFIAPI +SxSleepEntryCallBack ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext + ); + +EFI_STATUS +SaveRuntimeScriptTable ( + VOID + ); + + +#endif + diff --git a/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.c b/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.c new file mode 100644 index 0000000000..09a6a8c3b5 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.c @@ -0,0 +1,257 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + + SmmScriptSave.c + +Abstract: + + ScriptTableSave module at run time + +--*/ + +#include "SmmScriptSave.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 + ); + +VOID +SmmCopyMem ( + IN UINT8 *Destination, + IN UINT8 *Source, + IN UINTN ByteCount + ); + +// +// Function implementations +// +EFI_STATUS +SmmBootScriptWrite ( + IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable, + IN UINTN Type, + IN UINT16 OpCode, + ... + ) +{ + 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; + + default: + Status = EFI_SUCCESS; + break; + } + + return Status; +} + + +EFI_STATUS +SmmBootScriptCreateTable ( + IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable, + IN UINTN Type + ) +{ + 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 +SmmBootScriptCloseTable ( + IN EFI_SMM_SCRIPT_TABLE ScriptTableBase, + IN EFI_SMM_SCRIPT_TABLE ScriptTablePtr, + IN UINTN Type + ) +{ + 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; + UINTN Address; + UINTN Count; + UINT8 *Buffer; + UINTN NodeLength; + UINT8 WidthInByte; + + Width = VA_ARG(Marker, EFI_BOOT_SCRIPT_WIDTH); + Address = VA_ARG(Marker, UINTN); + 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; +} + +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/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.h b/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.h new file mode 100644 index 0000000000..e2e4bb6b27 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformSmm/SmmScriptSave.h @@ -0,0 +1,55 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + SmmScriptSave.h + +Abstract: + + This is an implementation of the BootScript at run time. + +--*/ + +#ifndef _RUNTIME_SCRIPT_SAVE_H +#define _RUNTIME_SCRIPT_SAVE_H + +#include "Efi.h" +#include "EfiBootScript.h" + + +typedef EFI_PHYSICAL_ADDRESS EFI_SMM_SCRIPT_TABLE; + +EFI_STATUS +SmmBootScriptCreateTable ( + IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable, + IN UINTN Type + ); + +EFI_STATUS +SmmBootScriptWrite ( + IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable, + IN UINTN Type, + IN UINT16 OpCode, + ... + ); + +EFI_STATUS +SmmBootScriptCloseTable ( + IN EFI_SMM_SCRIPT_TABLE ScriptTableBase, + IN EFI_SMM_SCRIPT_TABLE ScriptTablePtr, + IN UINTN Type + ); + +#endif diff --git a/Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.c b/Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.c new file mode 100644 index 0000000000..2f8996bc1a --- /dev/null +++ b/Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.c @@ -0,0 +1,160 @@ +/** + Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + PpmPolicy.c + +Abstract: + + This file is a wrapper for Intel PPM Platform Policy driver. + Get Setup Value to initilize Intel PPM DXE Platform Policy. + +--*/ +#include "PpmPolicy.h" +#include +#include +#include +#include + +#include +#include + +#define EFI_CPUID_FAMILY 0x0F00 +#define EFI_CPUID_MODEL 0x00F0 +#define EFI_CPUID_STEPPING 0x000F + + + +EFI_STATUS +EFIAPI +PpmPolicyEntry( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable +) +{ + EFI_MP_SERVICES_PROTOCOL *MpService; + EFI_CPUID_REGISTER Cpuid01 = { 0, 0, 0, 0}; + EFI_HANDLE Handle; + EFI_STATUS Status; + UINTN CpuCount; + UINT64 MaxRatio; + UINT8 CPUMobileFeature; + + PCH_STEPPING Stepping; + + + gBS = SystemTable->BootServices; + pBS = SystemTable->BootServices; + pRS = SystemTable->RuntimeServices; + + // + // Set PPM policy structure to known value + // + gBS->SetMem (&mDxePlatformPpmPolicy, sizeof(PPM_PLATFORM_POLICY_PROTOCOL), 0); + + // + // Find the MpService Protocol + // + Status = pBS->LocateProtocol (&gEfiMpServiceProtocolGuid, + NULL, + (void **)&MpService + ); + ASSERT_EFI_ERROR (Status); + + // + // Get processor count from MP service. + // + Status = MpService->GetNumberOfProcessors (MpService, &CpuCount, NULL); + ASSERT_EFI_ERROR (Status); + + // + // Store the CPUID for use by SETUP items. + // + AsmCpuid (EFI_CPUID_VERSION_INFO, &Cpuid01.RegEax, &Cpuid01.RegEbx, &Cpuid01.RegEcx, &Cpuid01.RegEdx); + MaxRatio = ((RShiftU64 (AsmReadMsr64(EFI_MSR_IA32_PLATFORM_ID), 8)) & 0x1F); + + + mDxePlatformPpmPolicy.Revision = PPM_PLATFORM_POLICY_PROTOCOL_REVISION_4; + + //Read CPU Mobile feature from PLATFORM_ID_MSR MSR(0x17) NOTFB_I_AM_NOT_MOBILE_FUSE_CLIAMC00H Bit 28 + //Bit Description: { Disables Mobile features 0 = I am NOT a mobile part 1 = I am a mobile part (default)"} + CPUMobileFeature = ((RShiftU64 (AsmReadMsr64(EFI_MSR_IA32_PLATFORM_ID), 28)) & 0x1); + + if (!EFI_ERROR(Status)) { + if (CPUMobileFeature == 1){//CPU mobile feature + mDxePlatformPpmPolicy.FunctionEnables.EnableGv = ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableCx = ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableCxe = ICH_DEVICE_DISABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableTm = ICH_DEVICE_ENABLE; + //MaxC7 + mDxePlatformPpmPolicy.FunctionEnables.EnableC7 = ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableC6 = ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableC4 = ICH_DEVICE_ENABLE; + + + }else{//CPU desktop feature + mDxePlatformPpmPolicy.FunctionEnables.EnableGv = ICH_DEVICE_DISABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableCx = ICH_DEVICE_DISABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableCxe = ICH_DEVICE_DISABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableTm = ICH_DEVICE_DISABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableC4 = ICH_DEVICE_DISABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableC6 = ICH_DEVICE_DISABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableC7 = ICH_DEVICE_DISABLE; + } + + + mDxePlatformPpmPolicy.FunctionEnables.EnableProcHot = ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.TStatesEnable = ICH_DEVICE_ENABLE; + + + Stepping = PchStepping(); + if (Stepping < PchB3) { + // If SoC is B0~B2 Stepping, disable the Turbo + mDxePlatformPpmPolicy.FunctionEnables.EnableTurboMode= ICH_DEVICE_DISABLE; + } else { + mDxePlatformPpmPolicy.FunctionEnables.EnableTurboMode= ICH_DEVICE_ENABLE; + } + + mDxePlatformPpmPolicy.FunctionEnables.EnableTm = ICH_DEVICE_ENABLE; + + mDxePlatformPpmPolicy.FunctionEnables.EnableCMP = ICH_DEVICE_ENABLE; + + } else { + mDxePlatformPpmPolicy.FunctionEnables.EnableGv = ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableCx = ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableCxe = ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableTm = ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableProcHot = ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableCMP = ICH_DEVICE_DISABLE; + mDxePlatformPpmPolicy.FunctionEnables.TStatesEnable = ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableTurboMode= ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableC4 = ICH_DEVICE_ENABLE; + mDxePlatformPpmPolicy.FunctionEnables.EnableC6 = ICH_DEVICE_ENABLE; + } + + + + mDxePlatformPpmPolicy.S3RestoreMsrSwSmiNumber = S3_RESTORE_MSR_SW_SMI; + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gPpmPlatformPolicyProtocolGuid, + &mDxePlatformPpmPolicy, + NULL + ); + + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.h b/Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.h new file mode 100644 index 0000000000..cd3676b3d8 --- /dev/null +++ b/Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.h @@ -0,0 +1,46 @@ +/** + Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + PpmPolicy.h + +Abstract: + + Header file for the PpmPolicyInitDxe Driver. + +--*/ +#include +// +// Driver Produced Protocol Prototypes +// +#include + +PPM_PLATFORM_POLICY_PROTOCOL mDxePlatformPpmPolicy; + +// Function Definition +#define ICH_DEVICE_ENABLE 1 +#define ICH_DEVICE_DISABLE 0 + +EFI_BOOT_SERVICES *gBS; +EFI_BOOT_SERVICES *pBS; +EFI_RUNTIME_SERVICES *pRS; + +#define POWER_STATE_SWITCH_SMI 43 +#define ENABLE_C_STATE_IO_REDIRECTION_SMI 70 +#define DISABLE_C_STATE_IO_REDIRECTION_SMI 71 +#define ENABLE_SMI_C_STATE_COORDINATION_SMI 72 +#define DISABLE_SMI_C_STATE_COORDINATION_SMI 73 +#define ENABLE_P_STATE_HARDWARE_COORDINATION_SMI 74 +#define DISABLE_P_STATE_HARDWARE_COORDINATION_SMI 75 +#define S3_RESTORE_MSR_SW_SMI 48 +#define ENABLE_C6_RESIDENCY_SMI 76 \ No newline at end of file diff --git a/Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.inf b/Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.inf new file mode 100644 index 0000000000..c5c6076a26 --- /dev/null +++ b/Vlv2TbltDevicePkg/PpmPolicy/PpmPolicy.inf @@ -0,0 +1,55 @@ +#/*++ +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# Module Name: +# +# PpmPolicy.inf +# +# Abstract: +# +# Implement platform power management policy +# +#--*/ + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = PpmPolicy + FILE_GUID = 2EE72E7C-FB9E-4318-B888-33A315C7A91D + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PpmPolicyEntry + +[Sources] + PpmPolicy.c + +[Packages] + MdePkg/MdePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + IA32FamilyCpuPkg/IA32FamilyCpuPkg.dec #CpuConfigLib.h + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + +[LibraryClasses] + DebugLib + BaseLib + PchPlatformLib + UefiDriverEntryPoint + +[Protocols] + gEfiMpServiceProtocolGuid + gPpmPlatformPolicyProtocolGuid + +[Guids] + gEfiSetupVariableGuid + +[Depex] + gEfiMpServiceProtocolGuid diff --git a/Vlv2TbltDevicePkg/SaveMemoryConfig/SaveMemoryConfig.c b/Vlv2TbltDevicePkg/SaveMemoryConfig/SaveMemoryConfig.c new file mode 100644 index 0000000000..dd3e5dc656 --- /dev/null +++ b/Vlv2TbltDevicePkg/SaveMemoryConfig/SaveMemoryConfig.c @@ -0,0 +1,187 @@ +/** + Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + SaveMemoryConfig.c + +Abstract: + This is the driver that locates the MemoryConfigurationData HOB, if it + exists, and saves the data to nvRAM. + + + +--*/ + +#include "SaveMemoryConfig.h" + +CHAR16 EfiMemoryConfigVariable[] = L"MemoryConfig"; + + +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=EFI_SUCCESS; + VOID *MemHobData; + VOID *VariableData; + UINTN BufferSize; + BOOLEAN MfgMode; + EFI_PLATFORM_SETUP_ID *BootModeBuffer; + EFI_PLATFORM_INFO_HOB *PlatformInfoHobPtr; + MEM_INFO_PROTOCOL *MemInfoProtocol; + EFI_HANDLE Handle; + UINT8 Channel, Slot; + VOID *GuidHob; + + VariableData = NULL; + MfgMode = FALSE; + Handle = NULL; + BootModeBuffer = NULL; + MemHobData = NULL; + PlatformInfoHobPtr = NULL; + BufferSize = 0; + + // + // Get Platform Info HOB + // + GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid); + if (GuidHob == NULL) { + Status = EFI_NOT_FOUND; + } + ASSERT_EFI_ERROR (Status); + + PlatformInfoHobPtr = GET_GUID_HOB_DATA (GuidHob); + + // + // Get the BootMode guid hob + // + GuidHob = GetFirstGuidHob (&gEfiPlatformBootModeGuid); + if (GuidHob == NULL) { + Status = EFI_NOT_FOUND; + } + ASSERT_EFI_ERROR (Status); + + BootModeBuffer = GET_GUID_HOB_DATA (GuidHob); + + + // + // Check whether in Manufacturing Mode + // + if (BootModeBuffer) { + if ( !CompareMem ( //EfiCompareMem + &BootModeBuffer->SetupName, + MANUFACTURE_SETUP_NAME, + StrSize (MANUFACTURE_SETUP_NAME) //EfiStrSize + ) ) { + MfgMode = TRUE; + } + } + + if (MfgMode) { + // + // Don't save Memory Configuration in Manufacturing Mode. Clear memory configuration. + // + Status = gRT->SetVariable ( + EfiMemoryConfigVariable, + &gEfiVlv2VariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, + NULL + ); + } else { + + MemInfoProtocol = (MEM_INFO_PROTOCOL*)AllocateZeroPool(sizeof(MEM_INFO_PROTOCOL)); + if (PlatformInfoHobPtr != NULL) { + MemInfoProtocol->MemInfoData.memSize = 0; + for (Channel = 0; Channel < CH_NUM; Channel ++){ + for (Slot = 0; Slot < DIMM_NUM; Slot ++){ + MemInfoProtocol->MemInfoData.dimmSize[Slot + (Channel * DIMM_NUM)] = PlatformInfoHobPtr->MemData.DimmSize[Slot]; + } + } + MemInfoProtocol->MemInfoData.memSize = PlatformInfoHobPtr->MemData.MemSize; + MemInfoProtocol->MemInfoData.EccSupport = PlatformInfoHobPtr->MemData.EccSupport; + MemInfoProtocol->MemInfoData.ddrFreq = PlatformInfoHobPtr->MemData.DdrFreq; + MemInfoProtocol->MemInfoData.ddrType = PlatformInfoHobPtr->MemData.DdrType; + if (MemInfoProtocol->MemInfoData.memSize == 0){ + // + // We hardcode if MRC didn't fill these info in + // + MemInfoProtocol->MemInfoData.memSize = 0x800; //per 1MB + MemInfoProtocol->MemInfoData.dimmSize[0] = 0x800; + MemInfoProtocol->MemInfoData.dimmSize[1] = 0; + MemInfoProtocol->MemInfoData.EccSupport = FALSE; + MemInfoProtocol->MemInfoData.ddrType = 5; //DDRType_LPDDR3 + } + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gMemInfoProtocolGuid, + MemInfoProtocol, + NULL + ); + } + + Status = EFI_SUCCESS; + if (BOOT_WITH_MINIMAL_CONFIGURATION != GetBootModeHob()){ + // + // Get the Memory Config guid hob + // + GuidHob = GetFirstGuidHob (&gEfiMemoryConfigDataGuid); + if (GuidHob == NULL) { + Status = EFI_NOT_FOUND; + } + ASSERT_EFI_ERROR (Status); + + MemHobData = GET_GUID_HOB_DATA (GuidHob); + BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob); + + Status = gRT->GetVariable ( + EfiMemoryConfigVariable, + &gEfiVlv2VariableGuid, + NULL, + &BufferSize, + VariableData + ); + if (EFI_ERROR(Status) && (MemHobData != NULL)) { + Status = gRT->SetVariable ( + EfiMemoryConfigVariable, + &gEfiVlv2VariableGuid, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS), + BufferSize, + MemHobData + ); + } + } + + } // if-else MfgMode + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/SaveMemoryConfig/SaveMemoryConfig.h b/Vlv2TbltDevicePkg/SaveMemoryConfig/SaveMemoryConfig.h new file mode 100644 index 0000000000..80e7376e44 --- /dev/null +++ b/Vlv2TbltDevicePkg/SaveMemoryConfig/SaveMemoryConfig.h @@ -0,0 +1,72 @@ +/** + Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + SaveMemoryConfig.h + +Abstract: + + Header file for Save Previous Memory Configuration Driver. + + + +--*/ + + +#ifndef _SAVE_MEMORY_CONFIG_DRIVER_H +#define _SAVE_MEMORY_CONFIG_DRIVER_H + +#include "Protocol/SetupMode.h" +#include "Guid/PlatformInfo.h" +#include "Library/HobLib.h" +#include "Library/DebugLib.h" +#include "Library/UefiBootServicesTableLib.h" +#include "Library/BaseMemoryLib.h" +#include "PlatformBootMode.h" +#include "Library/BaseLib.h" +#include "Library/UefiRuntimeServicesTableLib.h" +#include "Guid/GlobalVariable.h" +#include "Library/UefiLib.h" +#include "Guid/HobList.h" +#include "Guid/MemoryConfigData.h" +#include "Protocol/MemInfo.h" +#include "Library/MemoryAllocationLib.h" +#include + +// +// Prototypes +// +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 + +--*/ +; + +#endif diff --git a/Vlv2TbltDevicePkg/SaveMemoryConfig/SaveMemoryConfig.inf b/Vlv2TbltDevicePkg/SaveMemoryConfig/SaveMemoryConfig.inf new file mode 100644 index 0000000000..bea0ca7acc --- /dev/null +++ b/Vlv2TbltDevicePkg/SaveMemoryConfig/SaveMemoryConfig.inf @@ -0,0 +1,66 @@ +#/*++ +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +# Module Name: +# +# SaveMemoryConfig.inf +# +# Abstract: +# +# +--*/ + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = SaveMemoryConfig + FILE_GUID = E0ECBEC9-B193-4351-A488-36A655F22F9F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = SaveMemoryConfigEntryPoint + +[sources.common] + SaveMemoryConfig.c + +[Packages] + MdePkg/MdePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + HobLib + DebugLib + UefiRuntimeServicesTableLib + UefiLib + BaseLib + +[Protocols] + gMemInfoProtocolGuid + +[Guids] + gEfiMemoryConfigDataGuid + gEfiPlatformInfoGuid + gEfiPlatformBootModeGuid + gEfiVlv2VariableGuid + #gEfiHobListGuid + #gEfiPlatformInfoGuid + #gEfiPlatformBootModeGuid + #gEfiGlobalVariableGuid + #gEfiMemoryConfigDataGuid + +[Depex] + gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/CommonHeader.h b/Vlv2TbltDevicePkg/SmBiosMiscDxe/CommonHeader.h new file mode 100644 index 0000000000..4b7f70acc6 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/CommonHeader.h @@ -0,0 +1,44 @@ +/**@file + Common header file shared by all source files. + + This file includes package header files, library classes and protocol, PPI & GUID definitions. + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBaseBoardManufacturer.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBaseBoardManufacturer.uni new file mode 100644 index 0000000000000000000000000000000000000000..5d23abd534cd2d1f90fd1223c9bb7ab3e8c2c590 GIT binary patch literal 2866 zcmd6p-ER^>6vgkeiT}ffzG!WsH9nX|P59VWqLhY0t51ZlQj)T3fVT3_tG_eDGK+}` zwKXvtcJ9pFIdkUTb7%SaqhuwEY}a1#Jhx}`O6xYVs-^bLmNv7AjqTbN_`a}#y`+6@ z2Rv`E_E)__dVAP)OYj`o4Ym+wVCdarbb^&wk(n~{@(9>-*BjZKwKKcpJ;d{!Rjg$n za;(}gncx+HI|Fa*u&4BUU=L{*c#K?s0Nd22cxrCRx&;4-5wX!e6RaE1veOG?=2qV@ zH^539BjINFT0LCtaECnsp=W*G+V$445O!eV_nJD^8H$*R?_?bpohh}e+`5XLTaEtb z4K9J}y^FLs%7g;H2K`xG*&ZI3LUHQ*ktc#p~Muti-$VY$9NFVM))V4WO1m&7vh)J;8 z_R(T^ouQzno$xMOgMOW;M#NQZo6$NN>tMw$)*U;gjTu)=JVMAr9Zko0oIB(umb9#Q zfmXOeEznk6U%kB?yG!PU+H^Zcc8OQZF*{|v4yrJkZub^Fao3pkY~w2*?drXb@zw5M zX+JR|=BmMXwTnMRY+u$m0liKv&QO;2tWjxM+_E-Wk3@K;#9q3PLQcu+6zgd15!OV^ zH=ND}M4(5`Mzkr`41@-40?rlf04*r*s+1yD!m5B1tg_3zRO{D-UGogJZ?>P5nC%#W zny{aA<*VM`K>BOxx2bIh2`5AFT`VM&*D_?~**oadX6{#9kpV_kwE7d>+ z)y81>NIf;5E^#}iBHpffMY#5Ieo{7nn@K74;E_ypW9!ROMyt|#hiF&aSQeXY;?gE( z;k&B;8M=Y>U!>1{r0+x#%p%y2%c8zqVywDUg`I%C`TS38tK7?;vF^bx5pHs)gm2?^ L_4?4*>L&jM$4jNQ literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBaseBoardManufacturerData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBaseBoardManufacturerData.c new file mode 100644 index 0000000000..a3bacecd1d --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBaseBoardManufacturerData.c @@ -0,0 +1,63 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscBaseBoardManufacturerData.c + +Abstract: + + Static data of Base board manufacturer information. + Base board manufacturer information is Misc. subclass type 4 and SMBIOS type 2. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBaseBoardManufacturerFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBaseBoardManufacturerFunction.c new file mode 100644 index 0000000000..6570e7cfd2 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBaseBoardManufacturerFunction.c @@ -0,0 +1,232 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscBaseBoardManufacturerFunction.c + +Abstract: + + BaseBoard manufacturer information boot time changes. + SMBIOS type 2. + +--*/ + + +#include "CommonHeader.h" +#include "MiscSubclassDriver.h" +#include +#include "Library/DebugLib.h" +#include + + +/** + 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; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE2 *SmbiosRecord; + EFI_MISC_BASE_BOARD_MANUFACTURER *ForType2InputData; + + CHAR16 *MacStr; + EFI_HANDLE *Handles; + UINTN BufferSize; + + 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 = SmbiosMiscGetString (TokenToGet); + ManuStrLen = StrLen(Manufacturer); + if (ManuStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_PRODUCT_NAME1); + Product = SmbiosMiscGetString (TokenToGet); + ProductStrLen = StrLen(Product); + if (ProductStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_VERSION); + Version = SmbiosMiscGetString (TokenToGet); + VerStrLen = StrLen(Version); + if (VerStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + //Get handle infomation + // + BufferSize = 0; + Handles = NULL; + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiSimpleNetworkProtocolGuid, + NULL, + &BufferSize, + Handles + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + Handles = AllocateZeroPool(BufferSize); + if (Handles == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + Status = gBS->LocateHandle( + ByProtocol, + &gEfiSimpleNetworkProtocolGuid, + NULL, + &BufferSize, + Handles + ); + } + + // + //Get the MAC string + // + Status = NetLibGetMacString ( + *Handles, + NULL, + &MacStr + ); + if (EFI_ERROR (Status)) { + return Status; + } + SerialNumber = MacStr; + SerialNumStrLen = StrLen(SerialNumber); + if (SerialNumStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + DEBUG ((EFI_D_ERROR, "MAC Address: %S\n", MacStr)); + + TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_ASSET_TAG); + AssertTag = SmbiosMiscGetString (TokenToGet); + AssertTagStrLen = StrLen(AssertTag); + if (AssertTagStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = STRING_TOKEN (STR_MISC_BASE_BOARD_CHASSIS_LOCATION); + Chassis = SmbiosMiscGetString (TokenToGet); + ChassisStrLen = StrLen(Chassis); + if (ChassisStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE2) + ManuStrLen + 1 + ProductStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + AssertTagStrLen + 1 + ChassisStrLen +1 + 1); + ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE2) + 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 + // + 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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBiosVendor.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBiosVendor.uni new file mode 100644 index 0000000000000000000000000000000000000000..e9fffaef3ba0120220f56be0066c2c7c30e67311 GIT binary patch literal 1860 zcmb7_ZBJ7{5QXQniT~lId{KlJj4_6&NlUNV2$Ylp`iamN%1vl%ZcDL$UVYB&eJjxf zbJN|~-Pto|&&+Or|7uvnBHOlCe9!F}qejt3c4%|^VQWh*v5DQ<65kg#w3qa+ZIAB_ z)^0Z1XS9Reu^FCYyTcYj3WnNiW)rNL)mdq>E{_s>;iIuF*qhplc7*49Ygx}eR#^36 zlHe7An}RoS>?z}Gut)SuJjOmA!gg*`JhirF-wgkV8L?5E1nUm8{PaReefJ$}L#&xI z5^j#K-J>kR3OfPe+6J_WdhaZRT`~!=rp`J?5i{{k3SD%jx!qLuwd~B=jE^?Blw2QN ziy^JpZJsuPjS!_q&`YrvjCJY(JgfPLOuCBy4J#oxV*L}Z$E-G$32LtK8f5$DnFivt ztSGArT9S(cuQSzFP*?t`YhCC3DH&?OpsN0YnE~8KRNLlC9h6&sr6#4-w=WjM>y!%W z+GpCP9W(BrYJ{%p`^=Lh@Gdp3v1FA5(9=*p%+%>0|eSGDksKM(KzKZ^x{wphDt~(fK zQNk%=`&QtT=pD2;rLq*W%}vX7%loL9iSV4Gz3M_0azb9GSO_L5?u^l1c^TUSJDdE=l=%*7{SP$iJs> T+p~A%e9zv}>Ys0)HgNd^Yzq(% literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBiosVendorData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBiosVendorData.c new file mode 100644 index 0000000000..d18adad2b7 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBiosVendorData.c @@ -0,0 +1,106 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscBiosVendorData.c + +Abstract: + + Static data of BIOS vendor information. + BIOS vendor information is Misc. subclass type 2 and SMBIOS type 0. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_BIOS_VENDOR_DATA, MiscBiosVendor) += { + STRING_TOKEN(STR_MISC_BIOS_VENDOR), // BiosVendor + STRING_TOKEN(STR_MISC_BIOS_VERSION), // BiosVersion + STRING_TOKEN(STR_MISC_BIOS_RELEASE_DATE), // BiosReleaseDate + 0xF000, // BiosStartingAddress + { // BiosPhysicalDeviceSize + 1, // Value + 21 , // 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 + 0, // PrintScreenIsSupported :1 + 1, // Keyboard8042IsSupported :1 + 1, // SerialIsSupported :1 + 1, // PrinterIsSupported :1 + 1, // CgaMonoIsSupported :1 + 0, // NecPc98 :1 + +// +//BIOS Characteristics Extension Byte 1 +// + 1, // AcpiIsSupported :1 + 1, // UsbLegacyIsSupported :1 + 0, // AgpIsSupported :1 + 0, // I20BootIsSupported :1 + 0, // Ls120BootIsSupported :1 + 1, // AtapiZipDriveBootIsSupported :1 + 0, // Boot1394IsSupported :1 + 0, // SmartBatteryIsSupported :1 + +// +//BIOS Characteristics Extension Byte 2 +// + 1, // BiosBootSpecIsSupported :1 + 1, // FunctionKeyNetworkBootIsSupported :1 + 0x1 // Reserved :19 Bit 2 is SMBiosIsTargContDistEnabled + }, + { // BiosCharacteristics2 + 0x0001,// BiosReserved :16 Bit 0 is BIOS Splash Screen + 0, // SystemReserved :16 + 0 // Reserved :32 + }, + 0xFF, // BiosMajorRelease; + 0xFF, // BiosMinorRelease; + 0xFF, // BiosEmbeddedFirmwareMajorRelease; + 0xFF, // BiosEmbeddedFirmwareMinorRelease; +}; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBiosVendorFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBiosVendorFunction.c new file mode 100644 index 0000000000..33c14dcc74 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBiosVendorFunction.c @@ -0,0 +1,341 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscBiosVendorFunction.c + +Abstract: + + BIOS vendor information boot time changes. + Misc. subclass type 2. + SMBIOS type 0. + +--*/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" +#include +#include + +EFI_SPI_PROTOCOL *mSpiProtocol = NULL; + + +/** + This function read the data from Spi Rom. + + @param BaseAddress The starting address of the read. + @param Byte The pointer to the destination buffer. + @param Length The number of bytes. + @param SpiRegionType Spi Region Type. + + @retval Status + +**/ +EFI_STATUS +FlashRead ( + IN UINTN BaseAddress, + IN UINT8 *Byte, + IN UINTN Length, + IN SPI_REGION_TYPE SpiRegionType + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT32 SectorSize; + UINT32 SpiAddress; + UINT8 Buffer[SECTOR_SIZE_4KB]; + + SpiAddress = (UINT32)(UINTN)(BaseAddress); + SectorSize = SECTOR_SIZE_4KB; + + Status = mSpiProtocol->Execute ( + mSpiProtocol, + SPI_READ, + SPI_WREN, + TRUE, + TRUE, + FALSE, + (UINT32) SpiAddress, + SectorSize, + Buffer, + SpiRegionType + ); + + if (EFI_ERROR (Status)) { +#ifdef _SHOW_LOG_ + Print(L"Read SPI ROM Failed [%08x]\n", SpiAddress); +#endif + return Status; + } + + CopyMem (Byte, (void *)Buffer, Length); + + return Status; +} + +/** + 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; + CHAR16 *Version; + CHAR16 *ReleaseDate; + CHAR16 BiosVersion[100]; //Assuming that strings are < 100 UCHAR + CHAR16 BiosReleaseDate[100]; //Assuming that strings are < 100 UCHAR + CHAR16 BiosReleaseTime[100]; //Assuming that strings are < 100 UCHAR + EFI_STATUS Status; + EFI_STRING Char16String; + STRING_REF TokenToGet; + STRING_REF TokenToUpdate; + SMBIOS_TABLE_TYPE0 *SmbiosRecord; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_MISC_BIOS_VENDOR *ForType0InputData; + BIOS_ID_IMAGE BiosIdImage; + UINT16 UVerStr[32]; + UINTN LoopIndex; + UINTN CopyIndex; + MANIFEST_OEM_DATA *IFWIVerStruct; + UINT8 *Data8 = NULL; + UINT16 SpaceVer[2]={0x0020,0x0000}; + UINT16 BIOSVersionTemp[100]; + + ForType0InputData = (EFI_MISC_BIOS_VENDOR *)RecordData; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + GetBiosId (&BiosIdImage); + + // + // Add VLV2 BIOS Version and Release data + // + SetMem(BiosVersion, sizeof(BiosVersion), 0); + SetMem(BiosReleaseDate, sizeof(BiosReleaseDate), 0); + SetMem(BiosReleaseTime, sizeof(BiosReleaseTime), 0); + Status = GetBiosVersionDateTime (BiosVersion, BiosReleaseDate, BiosReleaseTime); + DEBUG ((EFI_D_ERROR, "GetBiosVersionDateTime :%s %s %s \n", BiosVersion, BiosReleaseDate, BiosReleaseTime)); + if (StrLen (BiosVersion) > 0) { + TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION); + HiiSetString (mHiiHandle, TokenToUpdate, BiosVersion, NULL); + } + + if (StrLen(BiosReleaseDate) > 0) { + TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE); + HiiSetString (mHiiHandle, TokenToUpdate, BiosReleaseDate, NULL); + } + + TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VENDOR); + Char16String = SmbiosMiscGetString (TokenToGet); + VendorStrLen = StrLen(Char16String); + if (VendorStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VERSION); + Version = SmbiosMiscGetString (TokenToGet); + + ZeroMem (UVerStr, 2*32); + ZeroMem (BIOSVersionTemp, 2*100); + StrCat (BIOSVersionTemp,Version); + Data8 = AllocatePool (SECTOR_SIZE_4KB); + ZeroMem (Data8, SECTOR_SIZE_4KB); + + Status = gBS->LocateProtocol ( + &gEfiSpiProtocolGuid, + NULL, + (VOID **)&mSpiProtocol + ); + if (!EFI_ERROR(Status)) { + // + // Get data form SPI ROM. + // + Status = FlashRead ( + MEM_IFWIVER_START, + Data8, + SECTOR_SIZE_4KB, + EnumSpiRegionAll + ); + if (!EFI_ERROR(Status)) { + for(LoopIndex = 0; LoopIndex <= SECTOR_SIZE_4KB; LoopIndex++) { + IFWIVerStruct = (MANIFEST_OEM_DATA *)(Data8 + LoopIndex); + if(IFWIVerStruct->Signature == SIGNATURE_32('$','F','U','D')) { + DEBUG ((EFI_D_ERROR, "the IFWI Length is:%d\n", IFWIVerStruct->IFWIVersionLen)); + if(IFWIVerStruct->IFWIVersionLen < 32) { + for(CopyIndex = 0; CopyIndex < IFWIVerStruct->IFWIVersionLen; CopyIndex++) { + UVerStr[CopyIndex] = (UINT16)IFWIVerStruct->IFWIVersion[CopyIndex]; + } + UVerStr[CopyIndex] = 0x0000; + DEBUG ((EFI_D_ERROR, "The IFWI Version is :%s,the IFWI Length is:%d\n", UVerStr,IFWIVerStruct->IFWIVersionLen)); + StrCat(BIOSVersionTemp,SpaceVer); + StrCat(BIOSVersionTemp,UVerStr); + DEBUG ((EFI_D_ERROR, "The BIOS and IFWI Version is :%s\n", BIOSVersionTemp)); + } + break; + } + } + } + } + FreePool(Data8); + + VerStrLen = StrLen(BIOSVersionTemp); + if (VerStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE); + ReleaseDate = SmbiosMiscGetString (TokenToGet); + DateStrLen = StrLen(ReleaseDate); + 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 = (UINT16)ForType0InputData->BiosStartingAddress; + + // + // ReleaseDate will be the 3rd optional string following the formatted structure. + // + SmbiosRecord->BiosReleaseDate = 3; + + // + // Tiger has no PCD value to indicate BIOS Size, just fill 0 for simply. + // + SmbiosRecord->BiosSize = 0; + SmbiosRecord->BiosCharacteristics = *(MISC_BIOS_CHARACTERISTICS*)(&ForType0InputData->BiosCharacteristics1); + + // + // CharacterExtensionBytes also store in ForType0InputData->BiosCharacteristics1 later two bytes to save size. + // + SmbiosRecord->BIOSCharacteristicsExtensionBytes[0] = *((UINT8 *) &ForType0InputData->BiosCharacteristics1 + 4); + SmbiosRecord->BIOSCharacteristicsExtensionBytes[1] = *((UINT8 *) &ForType0InputData->BiosCharacteristics1 + 5); + + SmbiosRecord->SystemBiosMajorRelease = ForType0InputData->BiosMajorRelease; + SmbiosRecord->SystemBiosMinorRelease = ForType0InputData->BiosMinorRelease; + SmbiosRecord->EmbeddedControllerFirmwareMajorRelease = ForType0InputData->BiosEmbeddedFirmwareMajorRelease; + SmbiosRecord->EmbeddedControllerFirmwareMinorRelease = ForType0InputData->BiosEmbeddedFirmwareMinorRelease; + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(Char16String, OptionalStrStart); + UnicodeStrToAsciiStr(BIOSVersionTemp, OptionalStrStart + VendorStrLen + 1); + UnicodeStrToAsciiStr(ReleaseDate, 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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBootInformationData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBootInformationData.c new file mode 100644 index 0000000000..43cad4b6f5 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBootInformationData.c @@ -0,0 +1,39 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscBootInformationData.c + +Abstract: + + Static data of Boot information. + Boot information is Misc. subclass type 26 and SMBIOS type 32. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_BOOT_INFORMATION_STATUS_DATA, BootInformationStatus) += { + EfiBootInformationStatusNoError, // BootInformationStatus + 0 // BootInformationData +}; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBootInformationFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBootInformationFunction.c new file mode 100644 index 0000000000..5a815c1ed6 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscBootInformationFunction.c @@ -0,0 +1,87 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscBootInformationFunction.c + +Abstract: + + boot information boot time changes. + SMBIOS type 32. + +--*/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.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(BootInformationStatus) +{ + 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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscChassisManufacturer.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscChassisManufacturer.uni new file mode 100644 index 0000000000000000000000000000000000000000..f56d85a94e191f1e51006a28cf34de6faa07720c GIT binary patch literal 2056 zcmchX-ER^>6vgkeiT}fdzG!VhjZcl50HrOdK*NXCC&E|hCS@@Tt@6*SzcaHiOA{0O zpxNxsotZo5o;h=7fBmdj#he}5E1u`}j9z8eI;-2#zS+hyOKfhpwkG$5P3$G@TYJs( zj_5e=y`gtR+_aR;ncWc!Ap=9-5u*uFYGr1s%qt^euY7N2E7oTAz;{aKd#hR3J{DN@ zVUm#Lz|Fv$d+Y`M5!h4OH5oJCpTKr$3ohTV?=CJCn356ZM%D+WPbG>a}%P} zGZO9=U#q8ig$LpUgprN;s_MOGA?(N`)LMAfTNE)9-(;tY_O!H{!n&IE?3DheJuZ>! zcdx~Suh{MHHi3;0rAE+8wN~`C>oGiw=iyAcivJBW;cUeE2U(9kZS*DrGo z#A#hnRt{Qo7AM|k@>Wn+`I*FY@r~-qc`YT4paG&C~{h2Z-x4co481?PK8t}Tp zK^;5iTeTMbCaOAgRoiE@iN^*+4X^dU+O!SErAa`D=g`E{4KjKjxkDr`>sz7~u24&~ zHQ!h7sKD-;d7*ZEMQ7J!bv?5-<4sV7(ec&0^u%3bs@W%3IjS16&d62uue6uUh`H`y zBd-#6(XcN&oQU2;iz}R^ny1{ft!~@a?M57#OSG3S*3E6kz>?_ z#e-)UavY}+Y?mB}Ks%uVe zUZGQ|ux@)t!@nwcbclZPQr(8U7v5VvKcX3VU|?sobsRGAo{@iDfyF&+=5W~OAtrS= z=>FZ)u4$J!n**4Izs27&`OL1munZnm{rE&Z{>(&df_6`>tQ(@6T*c8tuSSa-82tZl bE9=&)dY`(wq38c`&zGF_ + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscChassisManufacturerData.c + +Abstract: + + Static data is Chassis Manufacturer information. + Chassis Manufacturer information is Misc. subclass type 5 and SMBIOS type 3. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Chassis Manufacturer data. +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_CHASSIS_MANUFACTURER_DATA, 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 + EfiMiscChassisTypeUnknown, // ChassisType + 0, // ChassisLockPresent + 0 // Reserved + }, + EfiChassisStateSafe, // ChassisBootupState + EfiChassisStateSafe, // ChassisPowerSupplyState + EfiChassisStateOther, // ChassisThermalState + EfiChassisSecurityStatusOther, // ChassisSecurityState + 0, // ChassisOemDefined + 0, // ChassisHeight + 0, // ChassisNumberPowerCords + 0, // ChassisElementCount + 0, // ChassisElementRecordLength + { // ChassisElements + {0, 0, 0}, // ChassisElementType + 0, // ChassisElementStructure + EfiBaseBoardTypeUnknown, // ChassisBaseBoard + 0, // ChassisElementMinimum + 0 // ChassisElementMaximum + }, +}; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscChassisManufacturerFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscChassisManufacturerFunction.c new file mode 100644 index 0000000000..f503a2a640 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscChassisManufacturerFunction.c @@ -0,0 +1,155 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscChassisManufacturerFunction.c + +Abstract: + + Chassis manufacturer information boot time changes. + SMBIOS type 3. + +--*/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.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; + EFI_STRING Manufacturer; + EFI_STRING Version; + EFI_STRING SerialNumber; + EFI_STRING AssertTag; + STRING_REF TokenToGet; + 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; + } + + TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_MANUFACTURER); + Manufacturer = SmbiosMiscGetString (TokenToGet); + ManuStrLen = StrLen(Manufacturer); + if (ManuStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_VERSION); + Version = SmbiosMiscGetString (TokenToGet); + VerStrLen = StrLen(Version); + if (VerStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_SERIAL_NUMBER); + SerialNumber = SmbiosMiscGetString (TokenToGet); + SerialNumStrLen = StrLen(SerialNumber); + if (SerialNumStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = STRING_TOKEN (STR_MISC_CHASSIS_ASSET_TAG); + AssertTag = SmbiosMiscGetString (TokenToGet); + AssertTagStrLen = StrLen(AssertTag); + 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 = (UINT8)ForType3InputData->ChassisType.ChassisType; + + // + // 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 = (UINT8)ForType3InputData->ChassisBootupState; + SmbiosRecord->PowerSupplyState = (UINT8)ForType3InputData->ChassisPowerSupplyState; + SmbiosRecord->ThermalState = (UINT8)ForType3InputData->ChassisThermalState; + SmbiosRecord->SecurityStatus = (UINT8)ForType3InputData->ChassisSecurityState; + CopyMem (SmbiosRecord->OemDefined,(UINT8*)&ForType3InputData->ChassisOemDefined, 4); + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart); + UnicodeStrToAsciiStr(Version, OptionalStrStart + ManuStrLen + 1); + UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + ManuStrLen + 1 + VerStrLen + 1); + UnicodeStrToAsciiStr(AssertTag, 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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscMemoryDevice.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscMemoryDevice.uni new file mode 100644 index 0000000000000000000000000000000000000000..15b05b10c4e535eea20356b98f9ac28fa034c00a GIT binary patch literal 2904 zcmchYZEq4m6ov0sP5ciN`bBFC)|i+yYC`F@5(_jGtbQWprR^pK3`?v0dG$FnEW1>i zK+_n)yxuwY%(-{&{`p<9k~!P9*Zf}Cb7rMQ@2p~D`(ZPiSZr5zZBuMtTF+k5zqL2E zN9$~NF?(k_jH@=na$q-%g)jj_?FFkbqmdQaDYGw&3_J0&fhC-s*d1*j%MW&7P5YE% z)q+Wkl>>JI-j&B5GQR-3Pd~+C;O9Nqj%|pg_GX+LVeeQG8~KSD-GG+fUMLfP`i8w8 zqmgGM+!SA@`*RO>jAIZktV=7ex1NQtGbX{;(6dfa#7unSg)X|&*e-MD4(!YhnV&3i z$+-UXTJ&heZuzz`Y=kH^f?o2KFxRcS@XW`;}a_r987izxy?A;qURNCmKljt4WvUDo`CGY39PnY7%I_Y8SOn0qrE3$ zv|1sTi`&B*sTS4vJ)J(Q)!CHI=Gv(0)u~1IGibFs>*P<0_!w={v-jDoR%bIdn`=|^ z+O+M6zCtB$``WJW%)h^NxTwzdsFbQQo4zW2QS{|2^Da9?tg(Va%4!`hdg-A`t^2O^ iwG@jM{`F-${_hM<@!ItM>%>BJK723Jd*}O2H24dWgPIut literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscMemoryDeviceData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscMemoryDeviceData.c new file mode 100644 index 0000000000..9c22ba81b6 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscMemoryDeviceData.c @@ -0,0 +1,50 @@ +/*++ + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscMemoryDeviceData.c + +Abstract: + + Memory Device + Misc. subclass type 17. + SMBIOS type 17. + +--*/ + + +#include "CommonHeader.h" +#include "MiscSubclassDriver.h" + +MISC_SMBIOS_TABLE_DATA(EFI_MEMORY_ARRAY_LINK_DATA, MiscMemoryDevice) = { + STRING_TOKEN (STR_MISC_MEM_DEV_LOCATOR0), // Memory Device locator + STRING_TOKEN (STR_MISC_MEM_BANK_LOCATOR0), // Memory Bank Locator + STRING_TOKEN (STR_MISC_MEM_MANUFACTURER), // Memory manufacturer + STRING_TOKEN (STR_MISC_MEM_SERIAL_NO), // Memory serial Number + STRING_TOKEN (STR_MISC_MEM_ASSET_TAG), // Memory Asset Tag + STRING_TOKEN (STR_MISC_MEM_PART_NUMBER), // Memory Part Number + 0, // Memory Array Link + 0, // Memory SubArray link + 0, // UINT16 MemoryTotalWidth + 0, // UINT16 MemoryDatawidth + 0, // Memory Device Size + EfiMemoryFormFactorDip, // Memory Form Factor + 2, // UINT8 Memory Device type + EfiMemoryTypeDram, // Memory Type + 0, // Memory Type Detail + 0, // Memory Speed + 0 // Memory State + +}; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscMemoryDeviceFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscMemoryDeviceFunction.c new file mode 100644 index 0000000000..0f3f4d6a90 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscMemoryDeviceFunction.c @@ -0,0 +1,324 @@ +/*++ + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscMemoryDeviceFunction.c + +Abstract: + + Memory Device + Misc. subclass type 17. + SMBIOS type 17. + +--*/ + + +#include "CommonHeader.h" +#include "MiscSubclassDriver.h" +#include +#include +#include + + +#define FREQ_800 0x00 +#define FREQ_1066 0x01 +#define FREQ_1333 0x02 +#define FREQ_1600 0x03 + +#define MAX_SOCKETS 2 +#define EfiMemoryTypeDdr3 0x18 + +enum { + DDRType_DDR3 = 0, + DDRType_DDR3L = 1, + DDRType_DDR3U = 2, + DDRType_DDR3All = 3, + DDRType_LPDDR2 = 4, + DDRType_LPDDR3 = 5, + DDRType_DDR4 = 6 +}; + + +typedef struct { + EFI_PHYSICAL_ADDRESS MemoryArrayStartAddress; + EFI_PHYSICAL_ADDRESS MemoryArrayEndAddress; + EFI_INTER_LINK_DATA PhysicalMemoryArrayLink; + UINT16 MemoryArrayPartitionWidth; +} EFI_MEMORY_ARRAY_START_ADDRESS; + +/** + 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. + +**/ +VOID +GetType16Hndl ( + IN EFI_SMBIOS_PROTOCOL *Smbios, + OUT EFI_SMBIOS_HANDLE *Handle + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_TYPE RecordType; + EFI_SMBIOS_TABLE_HEADER *Buffer; + + *Handle = 0; + RecordType = EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY; + + Status = Smbios->GetNext ( + Smbios, + Handle, + &RecordType, + &Buffer, + NULL + ); + if (!EFI_ERROR(Status)) { + return; + } + *Handle = 0xFFFF; +} + +MISC_SMBIOS_TABLE_FUNCTION( MiscMemoryDevice ) +{ + CHAR8 *OptionalStrStart; + UINTN MemDeviceStrLen; + UINTN MemBankLocatorStrLen; + UINTN MemManufacturerStrLen; + UINTN MemSerialNumberStrLen; + UINTN MemAssetTagStrLen; + UINTN MemPartNumberStrLen; + CHAR16 *MemDevice; + CHAR16 *MemBankLocator; + CHAR16 *MemManufacturer; + CHAR16 *MemSerialNumber; + CHAR16 *MemAssetTag; + CHAR16 *MemPartNumber; + EFI_STATUS Status; + STRING_REF TokenToGet; + SMBIOS_TABLE_TYPE17 *SmbiosRecord; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_MEMORY_ARRAY_LINK_DATA *ForType17InputData; + UINT16 DdrFreq=0; + UINT16 Type16Handle=0; + MEM_INFO_PROTOCOL *MemInfoHob; + UINT8 MemoryType; + + UINT8 Dimm; + UINT8 NumSlots; + STRING_REF DevLocator[] = { + STRING_TOKEN(STR_MISC_MEM_DEV_LOCATOR0), STRING_TOKEN(STR_MISC_MEM_DEV_LOCATOR1) + }; + STRING_REF BankLocator[] = { + STRING_TOKEN(STR_MISC_MEM_BANK_LOCATOR0), STRING_TOKEN(STR_MISC_MEM_BANK_LOCATOR1) + }; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + ForType17InputData = (EFI_MEMORY_ARRAY_LINK_DATA *)RecordData; + + // + // Get Memory size parameters for each rank from the chipset registers + // + Status = gBS->LocateProtocol ( + &gMemInfoProtocolGuid, + NULL, + (void **)&MemInfoHob + ); + ASSERT_EFI_ERROR (Status); + + NumSlots = (UINT8)(MAX_SOCKETS); + + // + // Memory Freq + // + switch (MemInfoHob->MemInfoData.ddrFreq){ + case FREQ_800: + DdrFreq = 800; + break; + case FREQ_1066: + DdrFreq = 1066; + break; + case FREQ_1333: + DdrFreq = 1333; + break; + case FREQ_1600: + DdrFreq = 1600; + break; + default: + DdrFreq = 0; + break; + } + + // + // Memory Type + // + switch (MemInfoHob->MemInfoData.ddrType) { + case DDRType_LPDDR2: + MemoryType = EfiMemoryTypeDdr2; + break; + case DDRType_DDR3: + case DDRType_DDR3L: + case DDRType_DDR3U: + case DDRType_LPDDR3: + MemoryType = EfiMemoryTypeDdr3; + break; + default: + MemoryType = EfiMemoryTypeUnknown; + break; + } + + for (Dimm = 0; Dimm < NumSlots; Dimm++) { + // + // Memory Device Locator + // + TokenToGet = DevLocator[Dimm]; + MemDevice = SmbiosMiscGetString (TokenToGet); + MemDeviceStrLen = StrLen(MemDevice); + if (MemDeviceStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = DevLocator[Dimm]; + MemDevice = SmbiosMiscGetString (TokenToGet); + MemDeviceStrLen = StrLen(MemDevice); + if (MemDeviceStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Memory Bank Locator + // + TokenToGet = BankLocator[Dimm]; + MemBankLocator = SmbiosMiscGetString (TokenToGet); + MemBankLocatorStrLen = StrLen(MemBankLocator); + if (MemBankLocatorStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Memory Manufacturer + // + TokenToGet = STRING_TOKEN (STR_MISC_MEM_MANUFACTURER); + MemManufacturer = SmbiosMiscGetString (TokenToGet); + MemManufacturerStrLen = StrLen(MemManufacturer); + if (MemManufacturerStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Memory Serial Number + // + TokenToGet = STRING_TOKEN (STR_MISC_MEM_SERIAL_NO); + MemSerialNumber = SmbiosMiscGetString (TokenToGet); + MemSerialNumberStrLen = StrLen(MemSerialNumber); + if (MemSerialNumberStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Memory Asset Tag Number + // + TokenToGet = STRING_TOKEN (STR_MISC_MEM_ASSET_TAG); + MemAssetTag = SmbiosMiscGetString (TokenToGet); + MemAssetTagStrLen = StrLen(MemAssetTag); + if (MemAssetTagStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Memory Part Number + // + TokenToGet = STRING_TOKEN (STR_MISC_MEM_PART_NUMBER); + MemPartNumber = SmbiosMiscGetString (TokenToGet); + MemPartNumberStrLen = StrLen(MemPartNumber); + if (MemPartNumberStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE17) + MemDeviceStrLen + 1 + MemBankLocatorStrLen + 1 + MemManufacturerStrLen + 1 + MemSerialNumberStrLen + 1 + MemAssetTagStrLen+1 + MemPartNumberStrLen + 1 + 1); + ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE17) + MemDeviceStrLen + 1 + MemBankLocatorStrLen + 1 + MemManufacturerStrLen + 1 + MemSerialNumberStrLen + 1 + MemAssetTagStrLen+1 + MemPartNumberStrLen + 1 + 1); + + SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE17); + + // + // Make handle chosen by smbios protocol.add automatically. + // + SmbiosRecord->Hdr.Handle = 0; + + // + // Memory Array Handle will be the 3rd optional string following the formatted structure. + // + GetType16Hndl( Smbios, &Type16Handle); + SmbiosRecord->MemoryArrayHandle = Type16Handle; + + // + // Memory Size + // + if ((MemInfoHob->MemInfoData.dimmSize[Dimm])!=0){ + SmbiosRecord->TotalWidth = 32; + SmbiosRecord->DataWidth = 32; + SmbiosRecord->Size = MemInfoHob->MemInfoData.dimmSize[Dimm]; + SmbiosRecord->Speed = DdrFreq; + SmbiosRecord->ConfiguredMemoryClockSpeed = DdrFreq; + SmbiosRecord->FormFactor = EfiMemoryFormFactorDimm; + } + + SmbiosRecord->DeviceSet =(UINT8) ForType17InputData->MemoryDeviceSet; + SmbiosRecord->DeviceLocator= 1; + SmbiosRecord->BankLocator = 2; + + + SmbiosRecord->Manufacturer = 3; + SmbiosRecord->SerialNumber= 4; + SmbiosRecord->AssetTag= 5; + SmbiosRecord->PartNumber= 6; + SmbiosRecord->Attributes = (UINT8) ForType17InputData->MemoryState; + SmbiosRecord->MemoryType = MemoryType; + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(MemDevice, OptionalStrStart); + UnicodeStrToAsciiStr(MemBankLocator, OptionalStrStart + MemDeviceStrLen + 1); + UnicodeStrToAsciiStr(MemManufacturer, OptionalStrStart + MemDeviceStrLen + 1 + MemBankLocatorStrLen + 1); + UnicodeStrToAsciiStr(MemSerialNumber, OptionalStrStart + MemDeviceStrLen + 1 + MemBankLocatorStrLen + 1 + MemManufacturerStrLen + 1); + UnicodeStrToAsciiStr(MemAssetTag, OptionalStrStart + MemDeviceStrLen + 1 + MemBankLocatorStrLen + 1 + MemManufacturerStrLen + 1 + MemSerialNumberStrLen + 1); + UnicodeStrToAsciiStr(MemPartNumber, OptionalStrStart + MemDeviceStrLen + 1 + MemBankLocatorStrLen + 1 + MemManufacturerStrLen + 1 + MemSerialNumberStrLen + 1+ MemAssetTagStrLen+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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscNumberOfInstallableLanguagesData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscNumberOfInstallableLanguagesData.c new file mode 100644 index 0000000000..311f747c93 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscNumberOfInstallableLanguagesData.c @@ -0,0 +1,43 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscNumberOfInstallableLanguagesData.c + +Abstract: + + Static data of the Number of installable languages information. + Number of installable languages information is Misc. subclass type 11 and SMBIOS type 13. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES_DATA, NumberOfInstallableLanguages) += { + 1, // NumberOfInstallableLanguages + { // LanguageFlags + 1, // AbbreviatedLanguageFormat + 0 // Reserved + }, + STRING_TOKEN(STR_MISC_SYSTEM_LANGUAGE_EN_US) // CurrentLanguageNumber +}; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscNumberOfInstallableLanguagesFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscNumberOfInstallableLanguagesFunction.c new file mode 100644 index 0000000000..7cf3453a62 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscNumberOfInstallableLanguagesFunction.c @@ -0,0 +1,254 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscNumberOfInstallableLanguagesFunction.c + +Abstract: + + This driver parses the mSmbiosMiscDataTable structure and reports + any generated data. + +--*/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.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. + +**/ +VOID +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; + + Languages = HiiGetSupportedLanguages (HiiHandle); + if (Languages == NULL) { + return; + } + + 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. + // + 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 ; +} + + +/** + 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; + 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 + // + ZeroMem(CurrentLang, SMBIOS_STRING_MAX_LENGTH + 1); + 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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemString.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemString.uni new file mode 100644 index 0000000000000000000000000000000000000000..2162a797364ac1901b48c33520c0acd6051253f1 GIT binary patch literal 1848 zcmbuATTk0S5QXQtQvZV$UJ8W-P@hm+2})=qAVEne?UO|=fF+VtPN2=7Z~L8D$Lk>V zqE=RRXLe`L9G{tWetd6O!xG!Fmpsqy8D68D6MJVf`(jJWEwfv@vjwp)Y-pRz`?kyT z3TvnE_VBi`TQ((fZ1>ng$idKf&1!}? zm}EpH;O5}nI`#zr8tf7Cf{3yEL)gx2LZtSVoSPD#up&0flVRP1wt9P^Ub8Ek|oHG*EsHOJRm58zp?M`F@d{BPI^wGr!YL_KA-u1rvKNz|Y?KPxm4 zr$t3sb24DHny>X0^donRf55%EmI{<-(r5T0Y= zdfsokcXjWJtUOiCaOm|_Z>o+qF{oTAkw{?XZm zn1o7%JE6W?{vzuRUAI+y8HE+_-q?m)@-|Q=u+n!yH&~s$Lye_(4TZ&6oja#nYkqE{ zyo=$R6nZiBDykRHEM@Fd*VH~@sULs$L=I7zDvQ9QikI>Q-=`|Ow)fARQakZ(P2typ rrS4aJ{)f}`qvZcX2IwugCGp$ literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemStringData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemStringData.c new file mode 100644 index 0000000000..294be040af --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemStringData.c @@ -0,0 +1,39 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscOemStringData.c + +Abstract: + + Static data of OEM String information. + OEM String information is Misc. subclass type 9 and SMBIOS type 11. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_OEM_STRING, MiscOemString) = { + STRING_TOKEN(STR_INTEL_ETK_VER) +}; +MISC_SMBIOS_TABLE_DATA(EFI_MISC_OEM_STRING_DATA, OemString) += { STRING_TOKEN(STR_MISC_OEM_EN_US) }; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemStringFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemStringFunction.c new file mode 100644 index 0000000000..b53777cb0c --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemStringFunction.c @@ -0,0 +1,94 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + MiscOemStringFunction.c + +Abstract: + + boot information boot time changes. + SMBIOS type 11. + +--*/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.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(OemString) +{ + UINTN OemStrLen; + CHAR8 *OptionalStrStart; + EFI_STATUS Status; + EFI_STRING OemStr; + STRING_REF TokenToGet; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE11 *SmbiosRecord; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + + TokenToGet = STRING_TOKEN (STR_MISC_OEM_EN_US); + OemStr = SmbiosMiscGetString (TokenToGet); + 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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x90.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x90.uni new file mode 100644 index 0000000000000000000000000000000000000000..3b49a6e28e99f04bd9f1c9636b985f9b56e4ed55 GIT binary patch literal 2078 zcmc(fUrQT76vgjzq2FPNFRj%?ODR;^g3+j

=7_DRein$;|_O?$)l(q7=z)_r6LHn$(Pw8UbY*o~#czOtdcrhjWY zeDATgSKh9@vn}kV&4?V^Ew&I6Fw|Z#8e`3@%FI6Vipa4S?u~81+QjZ@M?`+Kx^?Yy zfmI(SF;Nk?33wC7p5kADJ)%#E7`s1&?cAnBYHrE88SxP#Vxv4U)-7n+?uC;0>RaZ9 zSTkoN+zelBO)rh*P?=#v&V`o?mul1R==o^fyCIKNohbEeC5YcnwHkP!kwn8sl zp;qYY?#tUMu)APhsBO;}*#%KuXVzl8392yKp1q4F?iy3hKCy~X)(~|>tg?Tn|H6!z z>kc+nS;8(F_HB)mqc^EV2W2VeAvZ0nTh>SGk%-7SwU;iWkQV1U#oAj(r&&JDKd$6s0O;wq6#WgCh&Es>cORjt0Wrlj5SR#*Y=lWn-Q zL3Q;uO#E%pE1*v|WE-uBU4@g +#include +#include + + +VOID +GetCPUStepping ( ) +{ + CHAR16 Buffer[40]; + + UINT16 FamilyId; + UINT8 Model; + UINT8 SteppingId; + UINT8 ProcessorType; + + + EfiCpuVersion (&FamilyId, &Model, &SteppingId, &ProcessorType); + + // + //we need raw Model data + // + Model = Model & 0xf; + + // + //Family/Model/Step + // + UnicodeSPrint (Buffer, sizeof (Buffer), L"%d/%d/%d", FamilyId, Model, SteppingId); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_PROCESSOR_STEPPING), Buffer, NULL); + +} + +EFI_STATUS +SearchChildHandle( + EFI_HANDLE Father, + EFI_HANDLE *Child + ) +{ + EFI_STATUS Status; + UINTN HandleIndex; + EFI_GUID **ProtocolGuidArray = NULL; + UINTN ArrayCount; + UINTN ProtocolIndex; + UINTN OpenInfoCount; + UINTN OpenInfoIndex; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo = NULL; + UINTN mHandleCount; + EFI_HANDLE *mHandleBuffer= NULL; + + // + // Retrieve the list of all handles from the handle database + // + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &mHandleCount, + &mHandleBuffer + ); + + for (HandleIndex = 0; HandleIndex < mHandleCount; HandleIndex++) { + // + // Retrieve the list of all the protocols on each handle + // + Status = gBS->ProtocolsPerHandle ( + mHandleBuffer[HandleIndex], + &ProtocolGuidArray, + &ArrayCount + ); + if (!EFI_ERROR (Status)) { + for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) { + Status = gBS->OpenProtocolInformation ( + mHandleBuffer[HandleIndex], + ProtocolGuidArray[ProtocolIndex], + &OpenInfo, + &OpenInfoCount + ); + + if (!EFI_ERROR (Status)) { + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { + if(OpenInfo[OpenInfoIndex].AgentHandle == Father) { + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) { + *Child = mHandleBuffer[HandleIndex]; + Status = EFI_SUCCESS; + goto TryReturn; + } + } + } + Status = EFI_NOT_FOUND; + } + } + if(OpenInfo != NULL) { + FreePool(OpenInfo); + OpenInfo = NULL; + } + } + if(ProtocolGuidArray != NULL) { + FreePool (ProtocolGuidArray); + ProtocolGuidArray = NULL; + } + } +TryReturn: + if(OpenInfo != NULL) { + FreePool (OpenInfo); + OpenInfo = NULL; + } + if(ProtocolGuidArray != NULL) { + FreePool(ProtocolGuidArray); + ProtocolGuidArray = NULL; + } + if(mHandleBuffer != NULL) { + FreePool (mHandleBuffer); + mHandleBuffer = NULL; + } + return Status; +} + +EFI_STATUS +JudgeHandleIsPCIDevice( + EFI_HANDLE Handle, + UINT8 Device, + UINT8 Funs + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH *DPath; + EFI_DEVICE_PATH *DevicePath; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DPath + ); + if(!EFI_ERROR(Status)) { + DevicePath = DPath; + while(!IsDevicePathEnd(DPath)) { + if((DPath->Type == HARDWARE_DEVICE_PATH) && (DPath->SubType == HW_PCI_DP)) { + PCI_DEVICE_PATH *PCIPath; + PCIPath = (PCI_DEVICE_PATH*) DPath; + DPath = NextDevicePathNode(DPath); + + if(IsDevicePathEnd(DPath) && (PCIPath->Device == Device) && (PCIPath->Function == Funs)) { + return EFI_SUCCESS; + } + } else { + DPath = NextDevicePathNode(DPath); + } + } + } + return EFI_UNSUPPORTED; +} + +EFI_STATUS +GetDriverName( + EFI_HANDLE Handle +) +{ + EFI_DRIVER_BINDING_PROTOCOL *BindHandle = NULL; + EFI_STATUS Status; + UINT32 Version; + UINT16 *Ptr; + CHAR16 Buffer[40]; + STRING_REF TokenToUpdate; + Status = gBS->OpenProtocol( + Handle, + &gEfiDriverBindingProtocolGuid, + (VOID**)&BindHandle, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR(Status)) { + return EFI_NOT_FOUND; + } + + Version = BindHandle->Version; + Ptr = (UINT16*)&Version; + UnicodeSPrint(Buffer, sizeof (Buffer), L"%d.%d.%d", Version >> 24 , (Version >>16)& 0x0f ,*(Ptr)); + + TokenToUpdate = (STRING_REF)STR_MISC_GOP_VERSION; + HiiSetString(mHiiHandle, TokenToUpdate, Buffer, NULL); + + return EFI_SUCCESS; +} + +EFI_STATUS +GetGOPDriverName() +{ + UINTN HandleCount; + EFI_HANDLE *Handles= NULL; + UINTN Index; + EFI_STATUS Status; + EFI_HANDLE Child = 0; + + Status = gBS->LocateHandleBuffer( + ByProtocol, + &gEfiDriverBindingProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + + for (Index = 0; Index < HandleCount ; Index++) { + Status = SearchChildHandle(Handles[Index], &Child); + if(!EFI_ERROR(Status)) { + Status = JudgeHandleIsPCIDevice(Child, 0x02, 0x00); + if(!EFI_ERROR(Status)) { + return GetDriverName(Handles[Index]); + } + } + } + return EFI_UNSUPPORTED; +} + +VOID +GetUcodeVersion() +{ + UINT32 MicroCodeVersion; + CHAR16 Buffer[40]; + + // + // Microcode Revision + // + EfiWriteMsr (EFI_MSR_IA32_BIOS_SIGN_ID, 0); + EfiCpuid (EFI_CPUID_VERSION_INFO, NULL); + MicroCodeVersion = (UINT32) RShiftU64 (EfiReadMsr (EFI_MSR_IA32_BIOS_SIGN_ID), 32); + UnicodeSPrint (Buffer, sizeof (Buffer), L"%x", MicroCodeVersion); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_UCODE_VERSION), Buffer, NULL); +} + +/** + Publish the smbios OEM type 0x90. + + @param Event - Event whose notification function is being invoked (gEfiDxeSmmReadyToLockProtocolGuid). + @param Context - Pointer to the notification functions context, which is implementation dependent. + + @retval None + +**/ +EFI_STATUS +EFIAPI +AddSmbiosT0x90Callback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINTN SECVerStrLen = 0; + UINTN uCodeVerStrLen = 0; + UINTN GOPStrLen = 0; + UINTN SteppingStrLen = 0; + SMBIOS_TABLE_TYPE90 *SmbiosRecord; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_MISC_OEM_TYPE_0x90 *ForType90InputData; + CHAR16 *SECVer; + CHAR16 *uCodeVer; + CHAR16 *GOPVer; + CHAR16 *Stepping; + STRING_REF TokenToGet; + CHAR8 *OptionalStrStart; + EFI_SMBIOS_PROTOCOL *SmbiosProtocol; + + ForType90InputData = (EFI_MISC_OEM_TYPE_0x90 *)Context; + + DEBUG ((EFI_D_INFO, "Executing SMBIOS T0x90 callback.\n")); + + gBS->CloseEvent (Event); // Unload this event. + + // + // First check for invalid parameters. + // + if (Context == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->LocateProtocol ( + &gEfiSmbiosProtocolGuid, + NULL, + (VOID *) &SmbiosProtocol + ); + ASSERT_EFI_ERROR (Status); + + GetUcodeVersion(); + GetGOPDriverName(); + GetCPUStepping(); + + TokenToGet = STRING_TOKEN (STR_MISC_SEC_VERSION); + SECVer = SmbiosMiscGetString (TokenToGet); + SECVerStrLen = StrLen(SECVer); + if (SECVerStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = STRING_TOKEN (STR_MISC_UCODE_VERSION); + uCodeVer = SmbiosMiscGetString (TokenToGet); + uCodeVerStrLen = StrLen(uCodeVer); + if (uCodeVerStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = STRING_TOKEN (STR_MISC_GOP_VERSION); + GOPVer = SmbiosMiscGetString (TokenToGet); + GOPStrLen = StrLen(GOPVer); + if (GOPStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_STEPPING); + Stepping = SmbiosMiscGetString (TokenToGet); + SteppingStrLen = StrLen(Stepping); + + + if (SteppingStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE90) + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1 + SteppingStrLen + 1 + 1); + ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE90) + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1 + SteppingStrLen + 1 + 1); + + SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_FIRMWARE_VERSION_INFO; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE90); + + // + // Make handle chosen by smbios protocol.add automatically. + // + SmbiosRecord->Hdr.Handle = 0; + + // + // SEC VERSION will be the 1st optional string following the formatted structure. + // + SmbiosRecord->SECVersion = 0; + + // + // Microcode VERSION will be the 2nd optional string following the formatted structure. + // + SmbiosRecord->uCodeVersion = 2; + + // + // GOP VERSION will be the 3rd optional string following the formatted structure. + // + SmbiosRecord->GOPVersion = 3; + + // + // CPU Stepping will be the 4th optional string following the formatted structure. + // + SmbiosRecord->CpuStepping = 4; + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(SECVer, OptionalStrStart); + UnicodeStrToAsciiStr(uCodeVer, OptionalStrStart + SECVerStrLen + 1); + UnicodeStrToAsciiStr(GOPVer, OptionalStrStart + SECVerStrLen + 1 + uCodeVerStrLen + 1); + UnicodeStrToAsciiStr(Stepping, OptionalStrStart + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1); + + // + // Now we have got the full smbios record, call smbios protocol to add this record. + // + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = SmbiosProtocol-> Add( + SmbiosProtocol, + NULL, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord + ); + + FreePool(SmbiosRecord); + return Status; +} + + +/** + This function makes boot time changes to the contents of the + MiscOemType0x90 (Type 0x90). + + @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(MiscOemType0x90) +{ + EFI_STATUS Status; + static BOOLEAN CallbackIsInstalledT0x90 = FALSE; + VOID *AddSmbiosT0x90CallbackNotifyReg; + EFI_EVENT AddSmbiosT0x90CallbackEvent; + + // + // This callback will create a OEM Type 0x90 record. + // + if (CallbackIsInstalledT0x90 == FALSE) { + CallbackIsInstalledT0x90 = TRUE; // Prevent more than 1 callback. + DEBUG ((EFI_D_INFO, "Create Smbios T0x90 callback.\n")); + + // + // gEfiDxeSmmReadyToLockProtocolGuid is ready + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + (EFI_EVENT_NOTIFY)AddSmbiosT0x90Callback, + RecordData, + &AddSmbiosT0x90CallbackEvent + ); + + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + + } + + Status = gBS->RegisterProtocolNotify ( + &gEfiDxeSmmReadyToLockProtocolGuid, + AddSmbiosT0x90CallbackEvent, + &AddSmbiosT0x90CallbackNotifyReg + ); + + return Status; + } + + return EFI_SUCCESS; + +} diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x94.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x94.uni new file mode 100644 index 0000000000000000000000000000000000000000..061ad6ab664a7b5e51779dd112683aca238355b0 GIT binary patch literal 4302 zcmd6pTW{M&5QXPCK>q__zch(2X;1`c&=#;{IS~>|f+Qk00Tgz;0r*>vDY=5?q zJ*RzbulT*8w>}^JV!zrN{kC0Vd2HwO0R0eD_g9~qVPTS(Xmb0o7pwb zBP@TnhV|{w5~>s=W2_SVX81dG-xrJz@O?x(!{XS-BhXIl0!yvkvhNc6gc+exoH4y~ zyyd5tm&|vcvo@l4>4@Yv_pjYY^9a}U$9OofL!OFyTte)GUq^;W+i5&pc%P%>pGLR0=u%$oa+tFpOK+W5R}=UGII#_BhhSdaK)uzn0(b$k)%efv}hqlGMI0+t#Jhaht z3yXn!?$VQ%^<1HqUwK`jZTMKDwGz5dtjlZHBPR9rI_1PTFzVECX1N_%L&{|7g9)v zyk5|IyRazsB&_ec&PL!o#xAAql<8M!={N3(4Oho_v9}y&%d;$nO3kxUgtC=l><}Zv z`wf<%UiXNRp^Qjbx&`!8g{-3$p<5wST2}>3QT>YVlb6*+U5EQE z=z5>CNqs5)pcVEHHC zP%RJmsonxxO?q8;>iQiZj9b*m5W6ZzPmO3u9A!y4+TmV!EOr%37(X?l9_Q|$lk^8d z^ey~|rFf329LLp}v=plBA>CB{R>$!O;}Gql=(}}aM_uuVs%NQ=;}AFCP;bR;bl3Lh z!&O*~5XSL{;}GqDr}4kh2va;FS;wJja$gL+Ha~)I57u;x)#0iRsyIygQfY!pUoHD^ z*5#MpxjXOATHV~m@|2^{4Il3H$Kv0&7SB^GOFj6}ch^2|AANcDYH?IgPjQ%XHKm?C zadsaQkIlui6q~uGv!k!xyYJt}kQ8fAkLew6=g;Kr`|uRY)POJ6w&SW({{>HV6cwi@ Py>;HyypPIw>LU6NY_>Zl literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x94Data.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x94Data.c new file mode 100644 index 0000000000..94847d5ed5 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x94Data.c @@ -0,0 +1,59 @@ +/*++ + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved. + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +Module Name: + + MiscOemType0x94Data.c + +Abstract: + + This file contains the Misc version Data (SMBIOS data type 0x94) + +--*/ + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + + +// +// Static (possibly build generated) Oem data. +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_OEM_TYPE_0x94, MiscOemType0x94) = { + +STRING_TOKEN (STR_MISC_GOP_VERSION), +STRING_TOKEN (STR_MISC_SEC_VERSION), +STRING_TOKEN (STR_MISC_MRC_VERSION_VALUE), +STRING_TOKEN (STR_MISC_UCODE_VERSION), +STRING_TOKEN (STR_MISC_PUNIT_FW_VALUE), +STRING_TOKEN (STR_MISC_PMC_FW_VALUE), +STRING_TOKEN (STR_MISC_ULPMC_FW_VALUE), +STRING_TOKEN (STR_MISC_SOC_VALUE), +STRING_TOKEN (STR_MISC_BOARD_ID_VALUE), +STRING_TOKEN (STR_MISC_FAB_ID_VALUE), +STRING_TOKEN (STR_MISC_CPU_FLAVOR_VALUE), +STRING_TOKEN (STR_MISC_BIOS_VERSION), +STRING_TOKEN (STR_MISC_PMIC_VERSION), +STRING_TOKEN (STR_MISC_TOUCH_VERSION), +STRING_TOKEN (STR_MISC_SECURE_BOOT), +STRING_TOKEN (STR_MISC_BOOT_MODE), +STRING_TOKEN (STR_MISC_SPEED_STEP), +STRING_TOKEN (STR_MISC_CPU_TURBO), +STRING_TOKEN (STR_MISC_CSTATE), +STRING_TOKEN (STR_MISC_GFX_TURBO), +STRING_TOKEN (STR_MISC_S0IX_VALUE), +STRING_TOKEN (STR_MISC_RC6_VALUE), + +}; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x94Function.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x94Function.c new file mode 100644 index 0000000000..898fc7cf0d --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOemType0x94Function.c @@ -0,0 +1,1223 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved. + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +Module Name: + + MiscOemType0x94Function.c + +Abstract: + + The function that processes the Smbios data type 0x94. + +--*/ + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "Valleyview.h" +#include "VlvAccess.h" +#include "PchAccess.h" +#include "SetupMode.h" +#include "PchCommonDefinitions.h" +#include + +typedef struct { + UINT8 RevId; + CHAR8 String[16]; +} SB_REV; + +// +// Silicon Steppings +// +SB_REV SBRevisionTable[] = { + {V_PCH_LPC_RID_0, "(A0 Stepping)"}, + {V_PCH_LPC_RID_1, "(A0 Stepping)"}, + {V_PCH_LPC_RID_2, "(A1 Stepping)"}, + {V_PCH_LPC_RID_3, "(A1 Stepping)"}, + {V_PCH_LPC_RID_4, "(B0 Stepping)"}, + {V_PCH_LPC_RID_5, "(B0 Stepping)"}, + {V_PCH_LPC_RID_6, "(B1 Stepping)"}, + {V_PCH_LPC_RID_7, "(B1 Stepping)"}, + {V_PCH_LPC_RID_8, "(B2 Stepping)"}, + {V_PCH_LPC_RID_9, "(B2 Stepping)"}, + {V_PCH_LPC_RID_A, "(B3 Stepping)"}, + {V_PCH_LPC_RID_B, "(B3 Stepping)"} +}; + +#define LEFT_JUSTIFY 0x01 +#define PREFIX_SIGN 0x02 +#define PREFIX_BLANK 0x04 +#define COMMA_TYPE 0x08 +#define LONG_TYPE 0x10 +#define PREFIX_ZERO 0x20 + +#define ICH_REG_REV 0x08 +#define MSR_IA32_PLATFORM_ID 0x17 +#define CHARACTER_NUMBER_FOR_VALUE 30 + + +UINT8 ReadBuffer[20]; //Version report length +UINT8 WriteBuffer[22] = {0x40,0x01,0x14,0x00,0x06,0x51,0x02,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //Version request + +/** + + VSPrint worker function that prints a Value as a decimal number in Buffer + + @param Buffer Location to place ascii decimal number string of Value. + @param Value Decimal value to convert to a string in Buffer. + @param Flags Flags to use in printing decimal string, see file header for details. + @param Width Width of hex value. + + @retval Number of characters printed. + +**/ +UINTN +EfiValueToString ( + IN OUT CHAR16 *Buffer, + IN INT64 Value, + IN UINTN Flags, + IN UINTN Width + ) +{ + CHAR16 TempBuffer[CHARACTER_NUMBER_FOR_VALUE]; + CHAR16 *TempStr; + CHAR16 *BufferPtr; + UINTN Count; + UINTN ValueCharNum; + UINTN Remainder; + CHAR16 Prefix; + UINTN Index; + BOOLEAN ValueIsNegative; + UINT64 TempValue; + + TempStr = TempBuffer; + BufferPtr = Buffer; + Count = 0; + ValueCharNum = 0; + ValueIsNegative = FALSE; + + if (Width > CHARACTER_NUMBER_FOR_VALUE - 1) { + Width = CHARACTER_NUMBER_FOR_VALUE - 1; + } + + if (Value < 0) { + Value = -Value; + ValueIsNegative = TRUE; + } + + do { + TempValue = Value; + Value = (INT64)DivU64x32 ((UINT64)Value, 10); + Remainder = (UINTN)((UINT64)TempValue - 10 * Value); + *(TempStr++) = (CHAR16)(Remainder + '0'); + ValueCharNum++; + Count++; + if ((Flags & COMMA_TYPE) == COMMA_TYPE) { + if (ValueCharNum % 3 == 0 && Value != 0) { + *(TempStr++) = ','; + Count++; + } + } + } while (Value != 0); + + if (ValueIsNegative) { + *(TempStr++) = '-'; + Count++; + } + + if ((Flags & PREFIX_ZERO) && !ValueIsNegative) { + Prefix = '0'; + } else { + Prefix = ' '; + } + + Index = Count; + if (!(Flags & LEFT_JUSTIFY)) { + for (; Index < Width; Index++) { + *(TempStr++) = Prefix; + } + } + + // + // Reverse temp string into Buffer. + // + if (Width > 0 && (UINTN) (TempStr - TempBuffer) > Width) { + TempStr = TempBuffer + Width; + } + Index = 0; + while (TempStr != TempBuffer) { + *(BufferPtr++) = *(--TempStr); + Index++; + } + + *BufferPtr = 0; + return Index; +} + +static CHAR16 mHexStr[] = { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', + L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' }; +/** + VSPrint worker function that prints a Value as a hex number in Buffer + + @param Buffer Location to place ascii hex string of Value. + @param Value Hex value to convert to a string in Buffer. + @param Flags Flags to use in printing Hex string, see file header for details. + @param Width Width of hex value. + + @retval Number of characters printed. + +**/ +UINTN +EfiValueToHexStr ( + IN OUT CHAR16 *Buffer, + IN UINT64 Value, + IN UINTN Flags, + IN UINTN Width + ) +{ + CHAR16 TempBuffer[CHARACTER_NUMBER_FOR_VALUE]; + CHAR16 *TempStr; + CHAR16 Prefix; + CHAR16 *BufferPtr; + UINTN Count; + UINTN Index; + + TempStr = TempBuffer; + BufferPtr = Buffer; + + // + // Count starts at one since we will null terminate. Each iteration of the + // loop picks off one nibble. Oh yea TempStr ends up backwards + // + Count = 0; + + if (Width > CHARACTER_NUMBER_FOR_VALUE - 1) { + Width = CHARACTER_NUMBER_FOR_VALUE - 1; + } + + do { + Index = ((UINTN)Value & 0xf); + *(TempStr++) = mHexStr[Index]; + Value = RShiftU64 (Value, 4); + Count++; + } while (Value != 0); + + if (Flags & PREFIX_ZERO) { + Prefix = '0'; + } else { + Prefix = ' '; + } + + Index = Count; + if (!(Flags & LEFT_JUSTIFY)) { + for (; Index < Width; Index++) { + *(TempStr++) = Prefix; + } + } + + // + // Reverse temp string into Buffer. + // + if (Width > 0 && (UINTN) (TempStr - TempBuffer) > Width) { + TempStr = TempBuffer + Width; + } + Index = 0; + while (TempStr != TempBuffer) { + *(BufferPtr++) = *(--TempStr); + Index++; + } + + *BufferPtr = 0; + return Index; +} + +/** + Converts MAC address to Unicode string. + The value is 64-bit and the resulting string will be 12 + digit hex number in pairs of digits separated by dashes. + + @param String - string that will contain the value + @param Val - value to convert + +**/ +CHAR16 * +StrMacToString ( + OUT CHAR16 *String, + IN EFI_MAC_ADDRESS *MacAddr, + IN UINT32 AddrSize + ) +{ + UINT32 i; + + for (i = 0; i < AddrSize; i++) { + + EfiValueToHexStr ( + &String[2 * i], + MacAddr->Addr[i] & 0xFF, + PREFIX_ZERO, + 2 + ); + } + + // + // Terminate the string. + // + String[2 * AddrSize] = L'\0'; + + return String; +} + + + +EFI_STATUS +TJudgeHandleIsPCIDevice( + EFI_HANDLE Handle, + UINT8 Device, + UINT8 Funs +) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH *DPath; + EFI_DEVICE_PATH *DevicePath; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DPath + ); + if(!EFI_ERROR(Status)) + { + DevicePath = DPath; + while(!IsDevicePathEnd(DPath)) + { + if((DPath->Type == HARDWARE_DEVICE_PATH) && (DPath->SubType == HW_PCI_DP)) + { + PCI_DEVICE_PATH *PCIPath; + + PCIPath = (PCI_DEVICE_PATH*) DPath; + DPath = NextDevicePathNode(DPath); + if(IsDevicePathEnd(DPath) && (PCIPath->Device == Device) && (PCIPath->Function == Funs)) + { + return EFI_SUCCESS; + } + } + else + { + DPath = NextDevicePathNode(DPath); + } + } + } + return EFI_UNSUPPORTED; +} + +EFI_STATUS +TSearchChildHandle( + EFI_HANDLE Father, + EFI_HANDLE *Child + ) +{ + EFI_STATUS Status; + UINTN HandleIndex; + EFI_GUID **ProtocolGuidArray = NULL; + UINTN ArrayCount; + UINTN ProtocolIndex; + UINTN OpenInfoCount; + UINTN OpenInfoIndex; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo = NULL; + UINTN mHandleCount; + EFI_HANDLE *mHandleBuffer= NULL; + + // + // Retrieve the list of all handles from the handle database + // + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &mHandleCount, + &mHandleBuffer + ); + + for (HandleIndex = 0; HandleIndex < mHandleCount; HandleIndex++) + { + // + // Retrieve the list of all the protocols on each handle + // + Status = gBS->ProtocolsPerHandle ( + mHandleBuffer[HandleIndex], + &ProtocolGuidArray, + &ArrayCount + ); + if (!EFI_ERROR (Status)) + { + for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) + { + Status = gBS->OpenProtocolInformation ( + mHandleBuffer[HandleIndex], + ProtocolGuidArray[ProtocolIndex], + &OpenInfo, + &OpenInfoCount + ); + if (!EFI_ERROR (Status)) + { + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) + { + if(OpenInfo[OpenInfoIndex].AgentHandle == Father) + { + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) + { + *Child = mHandleBuffer[HandleIndex]; + Status = EFI_SUCCESS; + goto TryReturn; + } + } + } + Status = EFI_NOT_FOUND; + } + } + if(OpenInfo != NULL) + { + FreePool(OpenInfo); + OpenInfo = NULL; + } + } + FreePool (ProtocolGuidArray); + ProtocolGuidArray = NULL; + } +TryReturn: + if(OpenInfo != NULL) + { + FreePool (OpenInfo); + OpenInfo = NULL; + } + if(ProtocolGuidArray != NULL) + { + FreePool(ProtocolGuidArray); + ProtocolGuidArray = NULL; + } + if(mHandleBuffer != NULL) + { + FreePool (mHandleBuffer); + mHandleBuffer = NULL; + } + return Status; +} + +EFI_STATUS +TGetDriverName( + EFI_HANDLE Handle, + CHAR16 *Name +) +{ + EFI_DRIVER_BINDING_PROTOCOL *BindHandle = NULL; + EFI_STATUS Status; + UINT32 Version; + UINT16 *Ptr; + Status = gBS->OpenProtocol( + Handle, + &gEfiDriverBindingProtocolGuid, + (VOID**)&BindHandle, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR(Status)) + { + return EFI_NOT_FOUND; + } + + Version = BindHandle->Version; + Ptr = (UINT16*)&Version; + UnicodeSPrint(Name, 40, L"%d.%d.%d", Version >> 24 , (Version >>16)& 0x0f ,*(Ptr)); + return EFI_SUCCESS; +} + +EFI_STATUS +TGetGOPDriverName( + CHAR16 *Name +) +{ + UINTN HandleCount; + EFI_HANDLE *Handles= NULL; + UINTN Index; + EFI_STATUS Status; + EFI_HANDLE Child = 0; + + Status = gBS->LocateHandleBuffer( + ByProtocol, + &gEfiDriverBindingProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + for (Index = 0; Index < HandleCount ; Index++) + { + Status = TSearchChildHandle(Handles[Index], &Child); + if(!EFI_ERROR(Status)) + { + Status = TJudgeHandleIsPCIDevice(Child, 0x02, 0x00); + if(!EFI_ERROR(Status)) + { + return TGetDriverName(Handles[Index], Name); + } + } + } + return EFI_UNSUPPORTED; +} + +EFI_STATUS +TGetTouchFirmwareVersion( + ) +{ + EFI_STATUS rc=EFI_SUCCESS; + UINTN TouchVer = 0; + UINTN Size = sizeof(UINTN); + + + CHAR16 Buffer[40]; + + rc = gRT->GetVariable( + L"TouchVer", + &gEfiVlv2VariableGuid, + NULL, + &Size, + &TouchVer + ); + if(!EFI_ERROR(rc)){ + UnicodeSPrint(Buffer, sizeof(Buffer), L"%02x.%02x", (TouchVer&0xFFFF)>>8,TouchVer&0xFF); + HiiSetString(mHiiHandle, STRING_TOKEN(STR_MISC_TOUCH_VERSION), Buffer, NULL); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +UpdatePlatformInformation ( + ) +{ + UINT32 MicroCodeVersion; + CHAR16 Buffer[40]; + UINT8 IgdVBIOSRevH; + UINT8 IgdVBIOSRevL; + UINT16 EDX; + EFI_IA32_REGISTER_SET RegSet; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios = NULL; + EFI_STATUS Status; + UINT8 CpuFlavor=0; + EFI_PEI_HOB_POINTERS GuidHob; + EFI_PLATFORM_INFO_HOB *mPlatformInfo=NULL; + UINTN NumHandles; + EFI_HANDLE *HandleBuffer; + UINTN Index; + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy; + UINTN PciD31F0RegBase; + UINT8 count; + UINT8 Data8; + UINT8 Data8_1; + + CHAR16 Name[40]; + UINT32 MrcVersion; + + UINT8 KscFwRevH =0; + UINT8 KscFwRevL =0; + + // + // Get the HOB list. If it is not present, then ASSERT. + // + GuidHob.Raw = GetHobList (); + if (GuidHob.Raw != NULL) { + if ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformInfoGuid, GuidHob.Raw)) != NULL) { + mPlatformInfo = GET_GUID_HOB_DATA (GuidHob.Guid); + } + } + + // + //VBIOS version + // + Status = gBS->LocateProtocol( + &gEfiLegacyBiosProtocolGuid, + NULL, + (VOID **)&LegacyBios + ); + + RegSet.X.AX = 0x5f01; + Status = LegacyBios->Int86 (LegacyBios, 0x10, &RegSet); + ASSERT_EFI_ERROR(Status); + + // + // simulate AMI int15 (ax=5f01) handler + // check NbInt15.asm in AMI code for asm edition + // + EDX = (UINT16)((RegSet.E.EBX >> 16) & 0xffff); + IgdVBIOSRevH = (UINT8)(((EDX & 0x0F00) >> 4) | (EDX & 0x000F)); + IgdVBIOSRevL = (UINT8)(((RegSet.X.BX & 0x0F00) >> 4) | (RegSet.X.BX & 0x000F)); + + if (IgdVBIOSRevH==0 && IgdVBIOSRevL==0) { + HiiSetString(mHiiHandle, STRING_TOKEN(STR_CHIP_IGD_VBIOS_REV_VALUE), L"N/A", NULL); + } else { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%02X%02X", IgdVBIOSRevH,IgdVBIOSRevL); + HiiSetString(mHiiHandle, STRING_TOKEN(STR_CHIP_IGD_VBIOS_REV_VALUE), Buffer, NULL); + } + + Status = TGetGOPDriverName(Name); + + if(!EFI_ERROR(Status)) + { + HiiSetString(mHiiHandle, STRING_TOKEN(STR_MISC_GOP_VERSION), Name, NULL); + } + + // + //CpuFlavor + // + //VLV + //VLV-DC Tablet 000 + //VLV-QC Notebook 001 + //VLV-QC Desktop 010 + // + //CPU flavor + // + CpuFlavor = RShiftU64 (EfiReadMsr (MSR_IA32_PLATFORM_ID), 50) & 0x07; + + switch(CpuFlavor){ + case 0x0: + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s (%01x)", L"VLV-DC Tablet", CpuFlavor); + break; + case 0x01: + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s (%01x)", L"VLV-QC Notebook", CpuFlavor); + break; + case 0x02: + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s (%01x)", L"VLV-QC Desktop", CpuFlavor); + break; + case 0x03: + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s (%01x)", L"VLV-QC Notebook", CpuFlavor); + break; + default: + UnicodeSPrint (Buffer, sizeof (Buffer), L"%s (%01x)", L"Unknown CPU", CpuFlavor); + break; + } + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_CPU_FLAVOR_VALUE), Buffer, NULL); + + if ( NULL != mPlatformInfo) { + // + // Board Id + // + UnicodeSPrint (Buffer, sizeof (Buffer), L"%x", mPlatformInfo->BoardId); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_BOARD_ID_VALUE), Buffer, NULL); + + // + // FAB ID + // + UnicodeSPrint (Buffer, sizeof (Buffer), L"%x", mPlatformInfo->BoardRev); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_FAB_ID_VALUE), Buffer, NULL); + } + + // + //Update MRC Version + // + MrcVersion = MmioRead32 (MmPciAddress (0, 0, 0, 0, 0xF0)); + MrcVersion &= 0xffff; + Index = EfiValueToString (Buffer, MrcVersion/100, PREFIX_ZERO, 0); + StrCat (Buffer, L"."); + EfiValueToString (Buffer + Index + 1, (MrcVersion%100)/10, PREFIX_ZERO, 0); + EfiValueToString (Buffer + Index + 2, (MrcVersion%100)%10, PREFIX_ZERO, 0); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_MRC_VERSION_VALUE), Buffer, NULL); + + // + //Update Soc Version + // + + // + // Retrieve all instances of PCH Platform Policy protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gDxePchPlatformPolicyProtocolGuid, + NULL, + &NumHandles, + &HandleBuffer + ); + if (!EFI_ERROR (Status)) { + // + // Find the matching PCH Policy protocol + // + for (Index = 0; Index < NumHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gDxePchPlatformPolicyProtocolGuid, + (VOID **) &PchPlatformPolicy + ); + if (!EFI_ERROR (Status)) { + PciD31F0RegBase = MmPciAddress ( + 0, + PchPlatformPolicy->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + + Data8 = MmioRead8 (PciD31F0RegBase + R_PCH_LPC_RID_CC); + count = sizeof (SBRevisionTable) / sizeof (SBRevisionTable[0]); + for (Index = 0; Index < count; Index++) { + if(Data8 == SBRevisionTable[Index].RevId) { + UnicodeSPrint (Buffer, sizeof (Buffer), L"%02x %a", Data8, SBRevisionTable[Index].String); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SOC_VALUE), Buffer, NULL); + break; + } + } + break; + } + } + } + + // + // Microcode Revision + // + EfiWriteMsr (EFI_MSR_IA32_BIOS_SIGN_ID, 0); + EfiCpuid (EFI_CPUID_VERSION_INFO, NULL); + MicroCodeVersion = (UINT32) RShiftU64 (EfiReadMsr (EFI_MSR_IA32_BIOS_SIGN_ID), 32); + UnicodeSPrint (Buffer, sizeof (Buffer), L"%x", MicroCodeVersion); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_PROCESSOR_MICROCODE_VALUE), Buffer, NULL); + + + // + //Secure boot + // + Data8 = SystemConfiguration.SecureBoot; + UnicodeSPrint (Buffer, sizeof(Buffer), L"%x", Data8); + HiiSetString(mHiiHandle, STRING_TOKEN(STR_MISC_SECURE_BOOT), Buffer, NULL); + + // + //Bootmode + // + BootMode = GetBootModeHob(); + UnicodeSPrint (Buffer, sizeof(Buffer), L"%x", BootMode); + HiiSetString(mHiiHandle, STRING_TOKEN(STR_MISC_BOOT_MODE), Buffer, NULL); + + // + //SpeedStep + // + Data8 = 1; + UnicodeSPrint (Buffer, sizeof(Buffer), L"%x", Data8); + HiiSetString(mHiiHandle, STRING_TOKEN(STR_MISC_SPEED_STEP), Buffer, NULL); + + // + //CPU Turbo + // + Data8 = 2; + UnicodeSPrint (Buffer, sizeof(Buffer), L"%x", Data8); + HiiSetString(mHiiHandle, STRING_TOKEN(STR_MISC_CPU_TURBO), Buffer, NULL); + + // + //CState + // + Data8 = 3; + UnicodeSPrint (Buffer, sizeof(Buffer), L"%x", Data8); + HiiSetString(mHiiHandle, STRING_TOKEN(STR_MISC_CSTATE), Buffer, NULL); + + // + //GFX Turbo + // + Data8 = SystemConfiguration.IgdTurboEnabled; + UnicodeSPrint (Buffer, sizeof(Buffer), L"%x", Data8); + HiiSetString(mHiiHandle, STRING_TOKEN(STR_MISC_GFX_TURBO), Buffer, NULL); + + Data8 = 0; + UnicodeSPrint (Buffer, sizeof(Buffer), L"%x", Data8); + HiiSetString(mHiiHandle, STRING_TOKEN(STR_MISC_S0IX_VALUE), Buffer, NULL); + + // + //RC6 + // + Data8 = 0; + UnicodeSPrint (Buffer, sizeof(Buffer), L"%x", Data8); + HiiSetString(mHiiHandle, STRING_TOKEN(STR_MISC_RC6_VALUE), Buffer, NULL); + + // + // Punit Version + // + Data8 = 0; + UnicodeSPrint (Buffer, sizeof (Buffer), L"0x%x", Data8); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_PUNIT_FW_VALUE), Buffer, NULL); + + // + // PMC Version + // + Data8 = (UINT8)((MmioRead32 (PMC_BASE_ADDRESS + R_PCH_PMC_PRSTS)>>16)&0x00FF); + Data8_1 = (UINT8)((MmioRead32 (PMC_BASE_ADDRESS + R_PCH_PMC_PRSTS)>>24)&0x00FF); + UnicodeSPrint (Buffer, sizeof (Buffer), L"0x%X_%X", Data8_1, Data8); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_PMC_FW_VALUE), Buffer, NULL); + + // + //PMIC Version + // + Status = ByteReadI2C(PMICI2cBus, PMICI2cAdd, PMICVendorOffset, 1, &Data8); + if(!EFI_ERROR(Status)){ + Status = ByteReadI2C(PMICI2cBus, PMICI2cAdd, PMICRevOffset, 1, &Data8_1); + if(!EFI_ERROR(Status)){ + UnicodeSPrint(Buffer, sizeof(Buffer), L"%02x.%02x", Data8, Data8_1); + HiiSetString(mHiiHandle, STRING_TOKEN(STR_MISC_PMIC_VERSION), Buffer, NULL); + } + } + + TGetTouchFirmwareVersion(); + + return EFI_SUCCESS; +} + + +/** + Smbios OEM type 0x94 callback. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification functions context, which is implementation dependent. + + @retval None + +**/ +VOID +AddSmbiosT0x94Callback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINTN SECVerStrLen = 0; + UINTN uCodeVerStrLen = 0; + UINTN GOPStrLen = 0; + UINTN MRCVersionStrLen = 0; + UINTN PMCVersionStrLen = 0; + UINTN ULPMCVersionStrLen = 0; + UINTN PUNITVersionStrLen = 0; + UINTN SOCVersionStrLen = 0; + UINTN BOARDVersionStrLen = 0; + UINTN FABVersionStrLen = 0; + UINTN CPUFLAVORStrLen = 0; + UINTN BIOSVersionStrLen = 0; + UINTN PMICVersionStrLen = 0; + UINTN TOUCHVersionStrLen = 0; + UINTN SecureBootModeLen = 0; + UINTN BootModeLen = 0; + UINTN SpeedStepModeLen = 0; + UINTN MaxCStateLen = 0; + UINTN CpuTurboLen = 0; + UINTN GfxTurboLen = 0; + UINTN IdleReserveLen = 0; + UINTN RC6Len = 0; + + SMBIOS_TABLE_TYPE94 *SmbiosRecord; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_MISC_OEM_TYPE_0x94 *ForType94InputData; + CHAR16 *SECVer; + CHAR16 *uCodeVer; + CHAR16 *GOPVer; + CHAR16 *MrcVer; + CHAR16 *PmcVer; + CHAR16 *UlpmcVer; + CHAR16 *PunitVer; + CHAR16 *SocVer; + CHAR16 *BoardVer; + CHAR16 *FabVer; + CHAR16 *CpuFlavor; + CHAR16 *BiosVer; + CHAR16 *PmicVer; + CHAR16 *TouchVer = L"15.16"; + CHAR16 *SecureBootMode; + CHAR16 *BootMode; + CHAR16 *SpeedStepMode; + CHAR16 *MaxCState; + CHAR16 *CpuTurbo; + CHAR16 *GfxTurbo; + CHAR16 *IdleReserve; + CHAR16 *RC6; + + UINTN RecordLen = 0; + UINTN StrIdx = 0; + + + STRING_REF TokenToGet; + CHAR8 *OptionalStrStart; + EFI_SMBIOS_PROTOCOL *SmbiosProtocol; + + ForType94InputData = (EFI_MISC_OEM_TYPE_0x94 *)Context; + + DEBUG ((EFI_D_INFO, "Executing SMBIOS T0x94 callback.\n")); + + gBS->CloseEvent (Event); // Unload this event. + + // + // First check for invalid parameters. + // + if (Context == NULL) { + return; + } + + UpdatePlatformInformation(); + + Status = gBS->LocateProtocol ( + &gEfiSmbiosProtocolGuid, + NULL, + (VOID **) &SmbiosProtocol + ); + ASSERT_EFI_ERROR (Status); + + TokenToGet = STRING_TOKEN (STR_MISC_SEC_VERSION); + SECVer = SmbiosMiscGetString (TokenToGet); + SECVerStrLen = StrLen(SECVer); + if (SECVerStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_UCODE_VERSION); + uCodeVer = SmbiosMiscGetString (TokenToGet); + uCodeVerStrLen = StrLen(uCodeVer); + if (uCodeVerStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_GOP_VERSION); + GOPVer = SmbiosMiscGetString (TokenToGet); + GOPStrLen = StrLen(GOPVer); + if (GOPStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_MRC_VERSION_VALUE); + MrcVer = SmbiosMiscGetString (TokenToGet); + MRCVersionStrLen = StrLen(MrcVer); + if (MRCVersionStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_PMC_FW_VALUE); + PmcVer = SmbiosMiscGetString (TokenToGet); + PMCVersionStrLen = StrLen(PmcVer); + if (PMCVersionStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_ULPMC_FW_VALUE); + UlpmcVer = SmbiosMiscGetString (TokenToGet); + ULPMCVersionStrLen = StrLen(UlpmcVer); + if (ULPMCVersionStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_PUNIT_FW_VALUE); + PunitVer = SmbiosMiscGetString (TokenToGet); + PUNITVersionStrLen = StrLen(PunitVer); + if (PUNITVersionStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_SOC_VALUE); + SocVer = SmbiosMiscGetString (TokenToGet); + SOCVersionStrLen = StrLen(SocVer); + if (SOCVersionStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_BOARD_ID_VALUE); + BoardVer = SmbiosMiscGetString (TokenToGet); + BOARDVersionStrLen = StrLen(BoardVer); + if (BOARDVersionStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_FAB_ID_VALUE); + FabVer = SmbiosMiscGetString (TokenToGet); + FABVersionStrLen = StrLen(FabVer); + if (FABVersionStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_CPU_FLAVOR_VALUE); + CpuFlavor = SmbiosMiscGetString (TokenToGet); + CPUFLAVORStrLen = StrLen(CpuFlavor); + if (CPUFLAVORStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VERSION); + BiosVer = SmbiosMiscGetString (TokenToGet); + BIOSVersionStrLen = StrLen(BiosVer); + if (BIOSVersionStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_PMIC_VERSION); + PmicVer = SmbiosMiscGetString (TokenToGet); + PMICVersionStrLen = StrLen(PmicVer); + if (PMICVersionStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_TOUCH_VERSION); + TouchVer = SmbiosMiscGetString (TokenToGet); + TOUCHVersionStrLen = StrLen(TouchVer); + if (TOUCHVersionStrLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_SECURE_BOOT); + SecureBootMode = SmbiosMiscGetString(TokenToGet); + SecureBootModeLen = StrLen(SecureBootMode); + if (SecureBootModeLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_BOOT_MODE); + BootMode = SmbiosMiscGetString(TokenToGet); + BootModeLen = StrLen(BootMode); + if (BootModeLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_SPEED_STEP); + SpeedStepMode = SmbiosMiscGetString(TokenToGet); + SpeedStepModeLen = StrLen(SpeedStepMode); + if (SpeedStepModeLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_CPU_TURBO); + CpuTurbo = SmbiosMiscGetString(TokenToGet); + CpuTurboLen = StrLen(CpuTurbo); + if (CpuTurboLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_CSTATE); + MaxCState = SmbiosMiscGetString(TokenToGet); + MaxCStateLen = StrLen(MaxCState); + if (MaxCStateLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_GFX_TURBO); + GfxTurbo = SmbiosMiscGetString(TokenToGet); + GfxTurboLen = StrLen(GfxTurbo); + if (GfxTurboLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_S0IX_VALUE); + IdleReserve = SmbiosMiscGetString(TokenToGet); + IdleReserveLen = StrLen(IdleReserve); + if (S0ixLen > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + TokenToGet = STRING_TOKEN (STR_MISC_RC6_VALUE); + RC6 = SmbiosMiscGetString(TokenToGet); + RC6Len = StrLen(RC6); + if (RC6Len > SMBIOS_STRING_MAX_LENGTH) { + return; + } + + RecordLen = sizeof (SMBIOS_TABLE_TYPE94) + SECVerStrLen + 1 + uCodeVerStrLen + 1 + GOPStrLen + 1 + PMCVersionStrLen + 1 + \ + TOUCHVersionStrLen + 1 + PMICVersionStrLen + 1 + BIOSVersionStrLen + 1 + CPUFLAVORStrLen + 1 + \ + BOARDVersionStrLen + 1 + FABVersionStrLen + 1 + PUNITVersionStrLen+ 1 + ULPMCVersionStrLen + 1 + \ + MRCVersionStrLen + 1 + SOCVersionStrLen + 1 + SecureBootModeLen + 1 + BootModeLen + 1 + \ + SpeedStepModeLen + 1 + CpuTurboLen + 1 + MaxCStateLen + 1 + GfxTurboLen + 1 + + RC6Len + 1 + 1; + + SmbiosRecord = AllocatePool(RecordLen); + + ZeroMem(SmbiosRecord, RecordLen); + + SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_MISC_VERSION_INFO; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE94); + + // + // Make handle chosen by smbios protocol.add automatically. + // + SmbiosRecord->Hdr.Handle = 0; + + SmbiosRecord->GopVersion = 1; + + SmbiosRecord->SECVersion = 2; + + SmbiosRecord->MRCVersion = 3; + + SmbiosRecord->uCodeVersion = 4; + + SmbiosRecord->PUnitVersion = 5; + + SmbiosRecord->PMCVersion = 6; + + SmbiosRecord->ULPMCVersion = 7; + + SmbiosRecord->SoCVersion = 8; + + SmbiosRecord->BoardVersion = 9; + + SmbiosRecord->FabVersion = 10; + + SmbiosRecord->CPUFlavor = 11; + + SmbiosRecord->BiosVersion = 12; + + SmbiosRecord->PmicVersion = 13; + + SmbiosRecord->TouchVersion = 14; + + SmbiosRecord->SecureBoot = 15; + + SmbiosRecord->BootMode = 16; + + SmbiosRecord->SpeedStepMode= 17; + + SmbiosRecord->CPUTurboMode = 18; + + SmbiosRecord->MaxCState = 19; + + SmbiosRecord->GfxTurbo = 20; + SmbiosRecord->IdleReserve = 21; + + SmbiosRecord->RC6 = 22; + + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(GOPVer, OptionalStrStart); + StrIdx += GOPStrLen + 1; + + UnicodeStrToAsciiStr(SECVer, OptionalStrStart + StrIdx); + StrIdx += SECVerStrLen + 1; + + UnicodeStrToAsciiStr(MrcVer, OptionalStrStart + StrIdx); + StrIdx += MRCVersionStrLen + 1; + + UnicodeStrToAsciiStr(uCodeVer, OptionalStrStart + StrIdx); + StrIdx += uCodeVerStrLen + 1; + + UnicodeStrToAsciiStr(PunitVer, OptionalStrStart + StrIdx); + StrIdx += PUNITVersionStrLen + 1; + + UnicodeStrToAsciiStr(PmcVer, OptionalStrStart + StrIdx); + StrIdx += PMCVersionStrLen + 1; + + UnicodeStrToAsciiStr(UlpmcVer, OptionalStrStart + StrIdx); + StrIdx += ULPMCVersionStrLen + 1; + + + UnicodeStrToAsciiStr(SocVer, OptionalStrStart + StrIdx); + StrIdx += SOCVersionStrLen +1; + + UnicodeStrToAsciiStr(BoardVer, OptionalStrStart + StrIdx); + StrIdx += BOARDVersionStrLen + 1; + + UnicodeStrToAsciiStr(FabVer, OptionalStrStart + StrIdx); + StrIdx += FABVersionStrLen + 1; + + UnicodeStrToAsciiStr(CpuFlavor, OptionalStrStart + StrIdx); + StrIdx += CPUFLAVORStrLen + 1; + + UnicodeStrToAsciiStr(BiosVer, OptionalStrStart + StrIdx); + StrIdx += BIOSVersionStrLen + 1; + + UnicodeStrToAsciiStr(PmicVer, OptionalStrStart + StrIdx); + StrIdx += PMICVersionStrLen + 1; + + UnicodeStrToAsciiStr(TouchVer, OptionalStrStart + StrIdx); + StrIdx += TOUCHVersionStrLen + 1; + + UnicodeStrToAsciiStr(SecureBootMode, OptionalStrStart + StrIdx); + StrIdx += SecureBootModeLen + 1; + + UnicodeStrToAsciiStr(BootMode, OptionalStrStart + StrIdx); + StrIdx += BootModeLen + 1; + + UnicodeStrToAsciiStr(SpeedStepMode, OptionalStrStart + StrIdx); + StrIdx += SpeedStepModeLen + 1; + + UnicodeStrToAsciiStr(CpuTurbo, OptionalStrStart + StrIdx); + StrIdx += CpuTurboLen + 1; + + UnicodeStrToAsciiStr(MaxCState, OptionalStrStart + StrIdx); + StrIdx += MaxCStateLen + 1; + + UnicodeStrToAsciiStr(GfxTurbo, OptionalStrStart + StrIdx); + StrIdx += GfxTurboLen + 1; + + UnicodeStrToAsciiStr(IdleReserve, OptionalStrStart + StrIdx); + StrIdx += S0ixLen + 1; + + UnicodeStrToAsciiStr(RC6, OptionalStrStart + StrIdx); + StrIdx += RC6Len + 1; + + // + // Now we have got the full smbios record, call smbios protocol to add this record. + // + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = SmbiosProtocol-> Add ( + SmbiosProtocol, + NULL, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord + ); + + FreePool(SmbiosRecord); + return; +} + +/** + This function makes boot time changes to the contents of the + MiscOemType0x94 (Type 0x94). + + @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(MiscOemType0x94) +{ + EFI_STATUS Status; + EFI_EVENT AddSmbiosT0x94CallbackEvent; + + Status = EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + AddSmbiosT0x94Callback, + RecordData, + &AddSmbiosT0x94CallbackEvent + ); + + ASSERT_EFI_ERROR (Status); + return Status; + +} diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOnboardDevice.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOnboardDevice.uni new file mode 100644 index 0000000000000000000000000000000000000000..bc06bad5816cf2d528ef262adf4bcfd5a70832bf GIT binary patch literal 1910 zcmbu9-A@xi6vgkeiT}f-ydXlW#wVgCEv?ufEhz=`iO>(qCbVmIOQHX~`a3h*ovn$9 zku;spd(S<4=FI&1*|3H=+q2jFUfK(0jk0%kWU2kIwPlvr%UN75zJV!|y$# zgJSlU**@d0Er^`jJ!2tcV5q%eHDR={Iy+7F6%ny>Kbu-kZe}am36USHWdr+EVKszF zLX-nH18?TB=ge=wp3pCenELq`wyDjD)ZUuB1@Vp*u~D6b(LHFJuNO+@v+vm(Gg^2? z!rkC2ds0+bF-}0Zu@SARK6ng$ClZ ztSBo7Ejf!r?=yKTsH^zQYhCC2Gft=hgR1&DDkJ3= z?U=S{r_8&k>d;mFkku|8yI|DuT3=X?zQejS2?+5Vx_G)n#JNZAGm@9p*64*R)Ea%u z&o$exu)AVksC{42*%eU(&#cFK7gS;Nef0q|ao3t^4vAHas)ne~#H#vt`V)4bd-*~R>2a=eMu%lY%yI0WdY_Hqx!}}N zqBFAFWUPu)t$T+gWq!3*)1S0lDn~CXRjN^{vyJbl5i2+ + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscOnboardDeviceData.c + +Abstract: + + Static data of Onboard device information . + The onboard device information is Misc. subclass type 8 and SMBIOS type 10. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_ONBOARD_DEVICE_DATA, 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_DATA, MiscOnboardDeviceAudio) = { + STRING_TOKEN(STR_MISC_ONBOARD_DEVICE_AUDIO), // OnBoardDeviceDescription + { // OnBoardDeviceStatus + EfiOnBoardDeviceTypeSound, // DeviceType + 1, // DeviceEnabled + 0 // Reserved + }, + 0 // OnBoardDevicePath +}; + diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOnboardDeviceFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOnboardDeviceFunction.c new file mode 100644 index 0000000000..ecf6e6e2bc --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscOnboardDeviceFunction.c @@ -0,0 +1,140 @@ +/** @file + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscOnboardDeviceFunction.c + +Abstract: + + Create the device path for the Onboard device. + The Onboard device information is Misc. subclass type 8 and SMBIOS type 10. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + + + +/** + This is a macro defined function, in fact, the function is + MiscOnboardDeviceFunction (RecordType, RecordLen, RecordData, LogRecordData) + This function makes boot time changes to the contents of the + MiscOnboardDevice structure. + + @param MiscOnboardDevice The string which is used to create the function + The Arguments in fact: + @param RecordType Type of record to be processed from the Data + Table. mMiscSubclassDataTable[].RecordType + @param RecordLen Size of static RecordData from the Data Table. + mMiscSubclassDataTable[].RecordLen + @param RecordData Pointer to RecordData, which will be written to + the Data Hub + @param LogRecordData TRUE to log RecordData to Data Hub. FALSE when + there is no more data to log. + + @retval EFI_SUCCESS *RecordData and *LogRecordData have been set. + @retval EFI_UNSUPPORTED Unexpected RecordType value. + @retval EFI_INVALID_PARAMETER One of the following parameter conditions was + true: RecordLen was zero. RecordData was NULL. + LogRecordData was NULL. + +**/ +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; + default: + break; + } + + DeviceDescription = SmbiosMiscGetString (TokenToGet); + 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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPhysicalArray.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPhysicalArray.uni new file mode 100644 index 0000000000000000000000000000000000000000..510ec40dbf5c594bfc0faf2497f03f71059b459a GIT binary patch literal 1518 zcmZXUTW=FF5QXO%iT_}wFHo8U5aOW%q=YW8f+kgxs_>Xwla+EoyCEfi9{7%(U2lq_ z*kjMknd9T}{{7RowmCbu7yO>u6IShNcJ|S>_R|iQTV@Me+K$*~Hnr!>ukEG1VszH5 zR&VSAJGBjwb6a5xAqPX_nB5F(V=X)#{ECR!go?a-q&tBo1Vr@Jl;g|HHepoNU!H}qBa={T?OB&7VkW*>rHjtAwfkCL*M@e*`r8SY$o0W%F=Z6H z)6-_K5u(%xdZ|{yTBn}Cvwk1Wq^tPf;|X^o*1w5*%<5E`pyq+7$uWO>)IgkeHD%R7 zJMQAr_nCStsH^zgYu)1fIXBdXL0$cVoeA7$bla(?1aZs?%CeP-;~ zHR}{r9lB~Bv76Fkw^)hS`qp~P3H#C{AjEq}>FI=sp-1jxsh2f2n1w6U26NZ1wYsRW zyTdQkzOU%)j;MiW)?+^fRTzC=eZWfGwWpdRVilvRA?g#cs{VudD;_b|8%&N>!YLB_ zUg1Ra6fJJ(EY-Z?rIossv#WL-kz2G^U#LTR-0K?avWkc~4*#|9vnl9H-dy2tQm?GT z-Re7VpqgGuR^``gb^J}MOV!c4T9tZ~>U6ypI?>}w;xLD!x=EdR%5R7_=I)44Cpx}o zZ)-Z#vj+J0{#4-$=D5M|mO_Q7L_MoXx1JxrsA3RUytgxNouP=n1q=Tz(W}=_FQQ3r b=u{1EMt*gCftC%Q7vkb5)VTWJDl7j3*3H^P literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPhysicalArrayData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPhysicalArrayData.c new file mode 100644 index 0000000000..43095e84de --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPhysicalArrayData.c @@ -0,0 +1,43 @@ +/*++ + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscPhysicalArrayData.c + +Abstract: + + BIOS Physical Array static data. + SMBIOS type 16. + +--*/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + + + +// +// Static (possibly build generated) Physical Memory Array Dat. +// +MISC_SMBIOS_TABLE_DATA(EFI_MEMORY_ARRAY_LOCATION_DATA, MiscPhysicalMemoryArray) = +{ + EfiMemoryArrayLocationSystemBoard, // Memory location + EfiMemoryArrayUseSystemMemory, // Memory array use + EfiMemoryErrorCorrectionNone, // Memory error correction + 0, // Maximum Memory Capacity + 0x01 // Number of Devices +}; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPhysicalArrayFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPhysicalArrayFunction.c new file mode 100644 index 0000000000..8f035cc925 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPhysicalArrayFunction.c @@ -0,0 +1,106 @@ +/*++ + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscPhysicalArrayFunction.c + +Abstract: + + BIOS system Physical Array boot time changes. + SMBIOS type 16. + +--*/ + + +#include "CommonHeader.h" +#include "MiscSubclassDriver.h" + + + +/** + This function makes boot time changes to the contents of the + MiscPhysicalArrayFunction (Type 16). + + @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(MiscPhysicalMemoryArray) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE16 *SmbiosRecord; + EFI_MEMORY_ARRAY_LOCATION_DATA *ForType16InputData; + UINT32 TopOfMemory = 8 * 1024 * 1024; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + + ForType16InputData = (EFI_MEMORY_ARRAY_LOCATION_DATA *)RecordData; + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE16) + 1); + ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE16) + 1); + + SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE16); + + // + // Make handle chosen by smbios protocol.add automatically. + // + SmbiosRecord->Hdr.Handle = 0; + + // + // ReleaseDate will be the 3rd optional string following the formatted structure. + // + SmbiosRecord->Location = *(UINT8 *) &ForType16InputData ->MemoryArrayLocation; + SmbiosRecord->Use = *(UINT8 *) &ForType16InputData ->MemoryArrayUse; + SmbiosRecord->MemoryErrorCorrection = *(UINT8 *) &ForType16InputData->MemoryErrorCorrection; + + // + // System does not provide the error information structure + // + SmbiosRecord->MemoryErrorInformationHandle = 0xFFFE; + + // + // Maximum memory capacity + // + SmbiosRecord-> MaximumCapacity = TopOfMemory; + SmbiosRecord-> NumberOfMemoryDevices= 0x02; + + // + // 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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPortInternalConnectorDesignator.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPortInternalConnectorDesignator.uni new file mode 100644 index 0000000000000000000000000000000000000000..c0e4b55f866fbae446233a9bd24509ade080c0ef GIT binary patch literal 2566 zcmb`IUr!T36vgkeiQi#UUKF7f@QJ8N3#%4|l2TH9BJ>Ys6WW^Xg7(X+zcaJl*+Nig zNW;#ZnLFp6Idf+C^Sfp>i)`KA@Ox=5=+%lgvOSyH51U(RiH+>aGIC#8-(J&h+gpC` zh&J=y7QGGPrcKBk+BLBdQZV$rU^F3`Se2PN^U4U=GuIp1jJ2uV@*R-*-Wt}nk0n+e zm?UIH;HKb>9QK(01=s`HjEte{_hCD=F`1g1vu;9u#E96aPC|4I+G6)YN!{ve=K4ev z$4Iyfe61ej6>fyGte8p~gw+U>7C^fuZsx_mpUH9NwK99(xtN33sU)v_{P%{f`UeEl@n zK%BCYvT{(yS?oHW$y;7s<)=>TD*I14p&AUz>dzSI!F_<+mS?J5#vozh0$`=+w{a;W2)I9S2?Qcvp$il>fdR|-_zgMp%;oG8&sa5b8GfwlT$B_w%6#h14RW$vpOu)Dv&3b=Ap(7w zMa0UxJbc!r?)j==5z~YIKNU_x47H>jq~0<=QQNOJv&DW`Km)Cr^xSZ+BzQ4 zh&;bVh42eZZeTQm$1)eOIpEblV4df&R=h9&=O9-;4~G+XFY4@K&)tnx*gT}jc1e$@ zbTo^p-dCfsq8ee{ WYE16mn}FEj|A~L|A9HuT3V#7!T7KRD literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPortInternalConnectorDesignatorData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPortInternalConnectorDesignatorData.c new file mode 100644 index 0000000000..2bc49932d8 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPortInternalConnectorDesignatorData.c @@ -0,0 +1,61 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscPortInternalConnectorDesignatorData.c + +Abstract: + + Static data of Port internal connector designator information. + Port internal connector designator information is Misc. subclass type 6 and + SMBIOS type 8. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Port connector designations +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortIde1) = { + STRING_TOKEN(STR_MISC_PORT_INTERNAL_IDE1), + STRING_TOKEN(STR_MISC_PORT_EXTERNAL_IDE1), + EfiPortConnectorTypeOnboardIde, + EfiPortConnectorTypeNone, + EfiPortTypeOther, + 0 +}; + +MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortIde2) = { + STRING_TOKEN(STR_MISC_PORT_INTERNAL_IDE2), + STRING_TOKEN(STR_MISC_PORT_EXTERNAL_IDE2), + EfiPortConnectorTypeOnboardIde, + EfiPortConnectorTypeNone, + EfiPortTypeOther, + 0 +}; + +MISC_SMBIOS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortAtxPower) = { + STRING_TOKEN(STR_MISC_PORT_INTERNAL_ATX_POWER), + STRING_TOKEN(STR_MISC_PORT_EXTERNAL_ATX_POWER), + EfiPortConnectorTypeOther, + EfiPortConnectorTypeNone, + EfiPortTypeOther, + 0 +}; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPortInternalConnectorDesignatorFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPortInternalConnectorDesignatorFunction.c new file mode 100644 index 0000000000..81e7613532 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscPortInternalConnectorDesignatorFunction.c @@ -0,0 +1,157 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscPortInternalConnectorDesignatorFunction.c + +Abstract: + + Create the device path for the Port internal connector designator. + Port internal connector designator information is Misc. subclass type 6 + and SMBIOS type 8. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + + +/** + This is a macro defined function, in fact, the function is + MiscPortInternalConnectorDesignatorFunction (RecordType, RecordLen, RecordData, LogRecordData) + This function makes boot time changes to the contents of the + MiscPortConnectorInformation. + + @param MiscPortInternalConnectorDesignator The string which is used to create + the function + The Arguments in fact: + @param RecordType Type of record to be processed from + the Data Table. + mMiscSubclassDataTable[].RecordType + @param RecordLen Size of static RecordData from the + Data Table. + mMiscSubclassDataTable[].RecordLen + @param RecordData Pointer to RecordData, which will be + written to the Data Hub + @param LogRecordData TRUE to log RecordData to Data Hub. + FALSE when there is no more data to + log. + + @retval EFI_SUCCESS *RecordData and *LogRecordData have + been set. + @retval EFI_UNSUPPORTED Unexpected RecordType value. + @retval EFI_INVALID_PARAMETER One of the following parameter + conditions was true: RecordLen was + zero. RecordData was NULL. + LogRecordData was NULL. + +**/ +MISC_SMBIOS_TABLE_FUNCTION ( + MiscPortInternalConnectorDesignator + ) +{ + CHAR8 *OptionalStrStart; + UINTN InternalRefStrLen; + UINTN ExternalRefStrLen; + EFI_STRING InternalRef; + EFI_STRING ExternalRef; + STRING_REF TokenForInternal; + STRING_REF TokenForExternal; + EFI_STATUS Status; + SMBIOS_TABLE_TYPE8 *SmbiosRecord; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR *ForType8InputData; + + ForType8InputData = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR *)RecordData; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + + TokenForInternal = 0; + TokenForExternal = 0; + + switch (ForType8InputData->PortInternalConnectorDesignator) { + + case STR_MISC_PORT_INTERNAL_IDE1: + TokenForInternal = STRING_TOKEN (STR_MISC_PORT_INTERNAL_IDE1); + TokenForExternal = STRING_TOKEN(STR_MISC_PORT_EXTERNAL_IDE1); + break; + case STR_MISC_PORT_INTERNAL_IDE2: + TokenForInternal = STRING_TOKEN (STR_MISC_PORT_INTERNAL_IDE2); + TokenForExternal = STRING_TOKEN(STR_MISC_PORT_EXTERNAL_IDE2); + break; + case STR_MISC_PORT_INTERNAL_ATX_POWER: + TokenForInternal = STRING_TOKEN (STR_MISC_PORT_INTERNAL_ATX_POWER); + TokenForExternal = STRING_TOKEN(STR_MISC_PORT_EXTERNAL_ATX_POWER); + break; + default: + break; + } + + InternalRef = SmbiosMiscGetString (TokenForInternal); + InternalRefStrLen = StrLen(InternalRef); + if (InternalRefStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + ExternalRef = SmbiosMiscGetString (TokenForExternal); + 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 = (UINT8)ForType8InputData->PortInternalConnectorType; + SmbiosRecord->ExternalReferenceDesignator = 2; + SmbiosRecord->ExternalConnectorType = (UINT8)ForType8InputData->PortExternalConnectorType; + SmbiosRecord->PortType = (UINT8)ForType8InputData->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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorCache.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorCache.uni new file mode 100644 index 0000000000000000000000000000000000000000..ee5736de5777bdff3825d6d07ea624404990bf0b GIT binary patch literal 1506 zcmZ{k-ER^>6vgkeiT}d}UbGgd#-~P2pk3>xwlqLfeQNkB-GmRbOR4hIiv-NmFK z%*>s+bMBclXZG)(mbEOhBYVg1wY?&06@6r9wz6NgwaikR*`uw=ePd&LOaH-6>^*H{ zjUxJJ$BYwOk~y_GV$&f1vK(isVN zkFVX6U4;$f6ojFTXjS#eSqQsi5^61+^&Umc#5XN;(V15EP}$e9zMT_)Kj2bweReIz zv|@L7+7vcIlo~-V)yj!=>JdDv_Ys+N75@iT!rh4VZ?gVpb*M~Gb4%7}w|}+MK%CYU zW#ynXcX8@IledDp%FkTuCg;z%p%x6P>gUXi;6A}^hbv7`9{HD=l%s)tvlw1CIH+qE zv~9a0PEa*MSM>vC6FhdyD0Z!H?V3JjUYZ1i@*WaA9h1>_c`2Bc_Ro3i*xAB_c`x2pVaJp)4U)bNkOGmr!ov;Gl zXRG_D&RO+RXa3UlCiRnF8{C{!tf8CM<;NTk)_k8(>crudg|AI;**&|uC~(QXf!({u g`lx?_p5?uUIxn{+uP6A;V06ezyiRzv`a0L_A2lD`r~m)} literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorCacheData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorCacheData.c new file mode 100644 index 0000000000..aed07ba876 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorCacheData.c @@ -0,0 +1,38 @@ +/*++ + +Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscBiosProcessorCache.c + +Abstract: + + Processor cache static data. + Misc. subclass type 7. + SMBIOS type 7. + +--*/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + + +// +// Static (possibly build generated) Processor cache data. +// +MISC_SMBIOS_TABLE_DATA(EFI_CACHE_VARIABLE_RECORD, MiscProcessorCache) = { +0 +}; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorCacheFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorCacheFunction.c new file mode 100644 index 0000000000..cbed988b13 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorCacheFunction.c @@ -0,0 +1,202 @@ +/*++ + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscProcessorCacheFunction.c + +Abstract: + + BIOS processor cache details. + Misc. subclass type 7. + SMBIOS type 7. + +--*/ +#include "CommonHeader.h" +#include "MiscSubclassDriver.h" +#include +#include + + +extern SMBIOS_TABLE_TYPE7 *SmbiosRecordL1; +extern SMBIOS_TABLE_TYPE7 *SmbiosRecordL2; +extern SMBIOS_TABLE_TYPE7 *SmbiosRecordL3; + + +UINT32 +ConvertBase2ToRaw ( + IN EFI_EXP_BASE2_DATA *Data) +{ + UINTN Index; + UINT32 RawData; + + RawData = Data->Value; + for (Index = 0; Index < (UINTN) Data->Exponent; Index++) { + RawData <<= 1; + } + + return RawData; +} + + +MISC_SMBIOS_TABLE_FUNCTION(MiscProcessorCache) +{ + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE7 *SmbiosRecordL1; + SMBIOS_TABLE_TYPE7 *SmbiosRecordL2; + + EFI_CACHE_SRAM_TYPE_DATA CacheSramType; + CHAR16 *SocketDesignation; + CHAR8 *OptionalStrStart; + UINTN SocketStrLen; + STRING_REF TokenToGet; + EFI_DATA_HUB_PROTOCOL *DataHub; + UINT64 MonotonicCount; + EFI_DATA_RECORD_HEADER *Record; + EFI_SUBCLASS_TYPE1_HEADER *DataHeader; + UINT8 *SrcData; + UINT32 SrcDataSize; + EFI_STATUS Status; + + // + // Memory Device LOcator + // + DEBUG ((EFI_D_ERROR, "type 7\n")); + + TokenToGet = STRING_TOKEN (STR_SOCKET_DESIGNATION); + SocketDesignation = SmbiosMiscGetString (TokenToGet); + SocketStrLen = StrLen(SocketDesignation); + if (SocketStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + SmbiosRecordL1 = AllocatePool(sizeof (SMBIOS_TABLE_TYPE7) + 7 + 1 + 1); + ASSERT (SmbiosRecordL1 != NULL); + ZeroMem(SmbiosRecordL1, sizeof (SMBIOS_TABLE_TYPE7) + 7 + 1 + 1); + + SmbiosRecordL2 = AllocatePool(sizeof (SMBIOS_TABLE_TYPE7) + 7 + 1 + 1); + ASSERT (SmbiosRecordL2 != NULL); + ZeroMem(SmbiosRecordL2, sizeof (SMBIOS_TABLE_TYPE7) + 7 + 1 + 1); + + // + // Get the Data Hub Protocol. Assume only one instance + // + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + (VOID **)&DataHub + ); + ASSERT_EFI_ERROR(Status); + + MonotonicCount = 0; + Record = NULL; + + do { + Status = DataHub->GetNextRecord ( + DataHub, + &MonotonicCount, + NULL, + &Record + ); + if (!EFI_ERROR(Status)) { + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) { + DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *)(Record + 1); + SrcData = (UINT8 *)(DataHeader + 1); + SrcDataSize = Record->RecordSize - Record->HeaderSize - sizeof (EFI_SUBCLASS_TYPE1_HEADER); + if (CompareGuid(&Record->DataRecordGuid, &gEfiCacheSubClassGuid) && (DataHeader->RecordType == CacheSizeRecordType)) { + if (DataHeader->SubInstance == EFI_CACHE_L1) { + SmbiosRecordL1->InstalledSize += (UINT16) (ConvertBase2ToRaw((EFI_EXP_BASE2_DATA *)SrcData) >> 10); + SmbiosRecordL1->MaximumCacheSize = SmbiosRecordL1->InstalledSize; + } + else if (DataHeader->SubInstance == EFI_CACHE_L2) { + SmbiosRecordL2->InstalledSize += (UINT16) (ConvertBase2ToRaw((EFI_EXP_BASE2_DATA *)SrcData) >> 10); + SmbiosRecordL2->MaximumCacheSize = SmbiosRecordL2->InstalledSize; + } else { + continue; + } + } + } + } + } while (!EFI_ERROR(Status) && (MonotonicCount != 0)); + + // + //Filling SMBIOS type 7 information for different cache levels. + // + + SmbiosRecordL1->Hdr.Type = EFI_SMBIOS_TYPE_CACHE_INFORMATION; + SmbiosRecordL1->Hdr.Length = (UINT8) sizeof (SMBIOS_TABLE_TYPE7); + SmbiosRecordL1->Hdr.Handle = 0; + + SmbiosRecordL1->Associativity = CacheAssociativity8Way; + SmbiosRecordL1->SystemCacheType = CacheTypeUnknown; + SmbiosRecordL1->SocketDesignation = 0x01; + SmbiosRecordL1->CacheSpeed = 0; + SmbiosRecordL1->CacheConfiguration = 0x0180; + ZeroMem (&CacheSramType, sizeof (EFI_CACHE_SRAM_TYPE_DATA)); + CacheSramType.Synchronous = 1; + CopyMem(&SmbiosRecordL1->SupportedSRAMType, &CacheSramType, 2); + CopyMem(&SmbiosRecordL1->CurrentSRAMType, &CacheSramType, 2); + SmbiosRecordL1->ErrorCorrectionType = EfiCacheErrorSingleBit; + + + SmbiosRecordL2->Hdr.Type = EFI_SMBIOS_TYPE_CACHE_INFORMATION; + SmbiosRecordL2->Hdr.Length = (UINT8) sizeof (SMBIOS_TABLE_TYPE7); + SmbiosRecordL2->Hdr.Handle = 0; + + SmbiosRecordL2->Associativity = CacheAssociativity16Way; + SmbiosRecordL2->SystemCacheType = CacheTypeInstruction; + SmbiosRecordL2->SocketDesignation = 0x01; + SmbiosRecordL2->CacheSpeed = 0; + SmbiosRecordL2->CacheConfiguration = 0x0281; + ZeroMem (&CacheSramType, sizeof (EFI_CACHE_SRAM_TYPE_DATA)); + CacheSramType.Synchronous = 1; + CopyMem(&SmbiosRecordL2->SupportedSRAMType, &CacheSramType, 2); + CopyMem(&SmbiosRecordL2->CurrentSRAMType, &CacheSramType, 2); + SmbiosRecordL2->ErrorCorrectionType = EfiCacheErrorSingleBit; + + + + // + //Adding SMBIOS type 7 records to SMBIOS table. + // + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + OptionalStrStart = (CHAR8 *)(SmbiosRecordL1 + 1); + UnicodeStrToAsciiStr(SocketDesignation, OptionalStrStart); + + Smbios-> Add( + Smbios, + NULL, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecordL1 + ); + + // + //VLV2 incorporates two SLM modules (quad cores) in the SoC. 2 cores share BIU/L2 cache + // + SmbiosRecordL2->InstalledSize = (SmbiosRecordL2->InstalledSize)/2; + SmbiosRecordL2->MaximumCacheSize = SmbiosRecordL2->InstalledSize; + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + + OptionalStrStart = (CHAR8 *)(SmbiosRecordL2 + 1); + UnicodeStrToAsciiStr(SocketDesignation, OptionalStrStart); + + Smbios-> Add( + Smbios, + NULL, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecordL2 + ); + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformation.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformation.uni new file mode 100644 index 0000000000000000000000000000000000000000..f07d978c7014ad96c162afa5eb77d8adf8daa6cf GIT binary patch literal 2208 zcmbW2QEw7K6ov1ziT`0kU$nNR8lM_9fkG>(K(mEbpPB-NZc@N36y?vW-4I{#CWAMYd~i_+HuzM%AK^?AYe^-PV>`ViUWwCBCn0Xs_wt*`d9q zjcmUdy|+E=md)_IwR>zKq+qDMVK%{<*#Rpx*5whf7jATG3-+eAq8;J+!Ri*R8RQ#`e{X5S3|h#9d_oCND0wEXl!N!{*y)`nO! z$4Iz2zIKnY2rKLagc}>sD(Zt{A?(1!$C^6UIf|HxZ&K)@GtF&W+E=#=YcT$@!6k70 z;j|diirwaE6W9n*YIwaAYr$Bj9>BAlkI1B}_>Wofxe@E1cs*vdsf<^1jn^RCKhHD} zr)5c5RnU@L9JxAEZFzO&pE|7%IDblpsxT<4zhGtn_Yu{$xpDx?9lxMSuzL2{n(#WO zg1UA}TeCLf7OF<*s=mi;iyG@=HJ#Rd>(DoumnI$|A@bztNwuBIde- z%`A#PMbo|(I03zd7Uxu!Vm7#Gxo&wM6*Cc@bF^1os6smAb&7RVc!WI>>upzOL(p|U zb%z#w%Bj*daBkh&iM#c>pZZk0`(#myR?txEs?7!USaJJ=vcuTlIREnain~T5 zRmQPh({}04K3Pg_JN1gx z&|4Yoqg&n0<=nPmri^XNLNASvs+!Tea7y2xmz_s_+;7WbyShCmQk>Q7-zR + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscOnboardDeviceData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to smbios. + +--*/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + + +/* + EFI_PROCESSOR_CORE_FREQUENCY_LIST_DATA ProcessorCoreFrequencyList; + EFI_PROCESSOR_FSB_FREQUENCY_LIST_DATA ProcessorFsbFrequencyList; + EFI_PROCESSOR_SERIAL_NUMBER_DATA ProcessorSerialNumber; + EFI_PROCESSOR_CORE_FREQUENCY_DATA ProcessorCoreFrequency; + EFI_PROCESSOR_FSB_FREQUENCY_DATA ProcessorFsbFrequency; + EFI_PROCESSOR_MAX_CORE_FREQUENCY_DATA ProcessorMaxCoreFrequency; + EFI_PROCESSOR_MAX_FSB_FREQUENCY_DATA ProcessorMaxFsbFrequency; + EFI_PROCESSOR_VERSION_DATA ProcessorVersion; + EFI_PROCESSOR_MANUFACTURER_DATA ProcessorManufacturer; + EFI_PROCESSOR_ID_DATA ProcessorId; + EFI_PROCESSOR_TYPE_DATA ProcessorType; + EFI_PROCESSOR_FAMILY_DATA ProcessorFamily; + EFI_PROCESSOR_VOLTAGE_DATA ProcessorVoltage; + EFI_PROCESSOR_APIC_BASE_ADDRESS_DATA ProcessorApicBase; + EFI_PROCESSOR_APIC_ID_DATA ProcessorApicId; + EFI_PROCESSOR_APIC_VERSION_NUMBER_DATA ProcessorApicVersionNumber; + EFI_PROCESSOR_MICROCODE_REVISION_DATA CpuUcodeRevisionData; + EFI_PROCESSOR_STATUS_DATA ProcessorStatus; + EFI_PROCESSOR_SOCKET_TYPE_DATA ProcessorSocketType; + EFI_PROCESSOR_SOCKET_NAME_DATA ProcessorSocketName; + EFI_PROCESSOR_ASSET_TAG_DATA ProcessorAssetTag; + EFI_PROCESSOR_HEALTH_STATUS ProcessorHealthStatus; + EFI_PROCESSOR_PACKAGE_NUMBER_DATA ProcessorPackageNumber; +} EFI_CPU_VARIABLE_RECORD; +*/ + + +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(EFI_CPU_DATA_RECORD, MiscProcessorInformation) = { + +0, + /* + STRING_TOKEN (STR_MISC_SOCKET_NAME), // Processor Socket Name + STRING_TOKEN (STR_MISC_PROCESSOR_MAUFACTURER), // Processor Manufacturer + STRING_TOKEN (STR_MISC_PROCESSOR_VERSION), // Processor Version Information + STRING_TOKEN (STR_MISC_PROCESSOR_SERIAL_NUMBER), // Serial Number + STRING_TOKEN (STR_MISC_ASSERT_TAG_DATA), // Processor Assert TAg Data + STRING_TOKEN (STR_MISC_PART_NUMBER) // Processor Part Numbe +*/ +}; + + + diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationFunction.c new file mode 100644 index 0000000000..005b43cde5 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationFunction.c @@ -0,0 +1,455 @@ +/*++ + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscProcessorInformationFunction.c + +Abstract: + + Onboard processor information boot time changes. + SMBIOS type 4. + +--*/ + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +#include +#include +#include +#include + +#define EfiProcessorFamilyIntelAtomProcessor 0x2B + +EFI_GUID mProcessorProducerGuid; + + +/** + Get cache SMBIOS record handle. + + @param Smbios Pointer to SMBIOS protocol instance. + @param CacheLevel Level of cache, starting from one. + @param Handle Returned record handle. + +**/ + +VOID +GetCacheHandle ( + IN EFI_SMBIOS_PROTOCOL *Smbios, + IN UINT8 CacheLevel, + OUT EFI_SMBIOS_HANDLE *Handle + ) +{ + UINT16 CacheConfig; + EFI_STATUS Status; + EFI_SMBIOS_TYPE RecordType; + EFI_SMBIOS_TABLE_HEADER *Buffer; + + *Handle = 0; + RecordType = EFI_SMBIOS_TYPE_CACHE_INFORMATION; + + do { + Status = Smbios->GetNext ( + Smbios, + Handle, + &RecordType, + &Buffer, + NULL + ); + if (!EFI_ERROR(Status)) { + CacheConfig = *(UINT16*)((UINT8*)Buffer + 5); + if ((CacheConfig & 0x7) == (CacheLevel -1) ) { + return; + } + } + } while (!EFI_ERROR(Status)); + + *Handle = 0xFFFF; +} + + +/** + This function makes boot time changes to the contents of the + MiscProcessorInformation (Type 4). + + @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. + +**/ +UINT32 +ConvertBase10ToRaw ( + IN EFI_EXP_BASE10_DATA *Data) +{ + UINTN Index; + UINT32 RawData; + + RawData = Data->Value; + for (Index = 0; Index < (UINTN) Data->Exponent; Index++) { + RawData *= 10; + } + + return RawData; +} + +#define BSEL_CR_OVERCLOCK_CONTROL 0xCD +#define FUSE_BSEL_MASK 0x03 + + + +UINT16 miFSBFrequencyTable[4] = { + 83, // 83.3MHz + 100, // 100MHz + 133, // 133MHz + 117 // 116.7MHz +}; + +/** + Determine the processor core frequency + + @param None + + @retval Processor core frequency multiplied by 3 + + +**/ +UINT16 +DetermineiFsbFromMsr ( + VOID + ) +{ + // + // Determine the processor core frequency + // + UINT64 Temp; + Temp = (EfiReadMsr (BSEL_CR_OVERCLOCK_CONTROL)) & FUSE_BSEL_MASK; + return miFSBFrequencyTable[(UINT32)(Temp)]; + +} + +MISC_SMBIOS_TABLE_FUNCTION (MiscProcessorInformation) +{ + CHAR8 *OptionalStrStart; + EFI_STRING SerialNumber; + CHAR16 *Version=NULL; + CHAR16 *Manufacturer=NULL; + CHAR16 *Socket=NULL; + CHAR16 *AssetTag=NULL; + CHAR16 *PartNumber=NULL; + UINTN SerialNumberStrLen=0; + UINTN VersionStrLen=0; + UINTN ManufacturerStrLen=0; + UINTN SocketStrLen=0; + UINTN AssetTagStrLen=0; + UINTN PartNumberStrLen=0; + UINTN ProcessorVoltage=0xAE; + UINT32 Eax01; + UINT32 Ebx01; + UINT32 Ecx01; + UINT32 Edx01; + STRING_REF TokenToGet; + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE4 *SmbiosRecord; + EFI_CPU_DATA_RECORD *ForType4InputData; + UINT16 L1CacheHandle=0; + UINT16 L2CacheHandle=0; + UINT16 L3CacheHandle=0; + UINTN NumberOfEnabledProcessors=0 ; + UINTN NumberOfProcessors=0; + UINT64 Frequency = 0; + EFI_MP_SERVICES_PROTOCOL *MpService; + EFI_DATA_HUB_PROTOCOL *DataHub; + UINT64 MonotonicCount; + EFI_DATA_RECORD_HEADER *Record; + EFI_SUBCLASS_TYPE1_HEADER *DataHeader; + UINT8 *SrcData; + UINT32 SrcDataSize; + EFI_PROCESSOR_VERSION_DATA *ProcessorVersion; + CHAR16 *NewStringToken; + STRING_REF TokenToUpdate; + PROCESSOR_ID_DATA *ProcessorId = NULL; + + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + + ForType4InputData = (EFI_CPU_DATA_RECORD *)RecordData; + + ProcessorId = AllocateZeroPool(sizeof(PROCESSOR_ID_DATA)); + if (ProcessorId == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Get the Data Hub Protocol. Assume only one instance + // + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + (VOID **)&DataHub + ); + ASSERT_EFI_ERROR(Status); + + MonotonicCount = 0; + Record = NULL; + + do { + Status = DataHub->GetNextRecord ( + DataHub, + &MonotonicCount, + NULL, + &Record + ); + if (!EFI_ERROR(Status)) { + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) { + + DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *)(Record + 1); + SrcData = (UINT8 *)(DataHeader + 1); + SrcDataSize = Record->RecordSize - Record->HeaderSize - sizeof (EFI_SUBCLASS_TYPE1_HEADER); + + // + // Processor + // + if (CompareGuid(&Record->DataRecordGuid, &gEfiProcessorSubClassGuid)) { + CopyMem (&mProcessorProducerGuid, &Record->ProducerName, sizeof(EFI_GUID)); + switch (DataHeader->RecordType) { + case ProcessorVoltageRecordType: + ProcessorVoltage = (((EFI_EXP_BASE10_DATA *)SrcData)->Value)/100 + 0x80; + break; + case ProcessorCoreFrequencyRecordType: + DEBUG ((EFI_D_ERROR, "ProcessorCoreFrequencyRecordType SrcData1 =%d\n", ConvertBase10ToRaw((EFI_EXP_BASE10_DATA *)SrcData)/1000000)); + Frequency = (ConvertBase10ToRaw((EFI_EXP_BASE10_DATA *)SrcData)/1000000); + break; + case ProcessorVersionRecordType: + ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *)SrcData; + NewStringToken = HiiGetPackageString(&mProcessorProducerGuid, *ProcessorVersion, NULL); + TokenToUpdate = (STRING_REF)STR_MISC_PROCESSOR_VERSION; + HiiSetString(mHiiHandle, TokenToUpdate, NewStringToken, NULL); + break; + default: + break; + } + } + } + } + } while (!EFI_ERROR(Status) && (MonotonicCount != 0)); + + // + // Token to get for Socket Name + // + TokenToGet = STRING_TOKEN (STR_MISC_SOCKET_NAME); + Socket = SmbiosMiscGetString (TokenToGet); + SocketStrLen = StrLen(Socket); + if (SocketStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Token to get for Processor Manufacturer + // + TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_MAUFACTURER); + Manufacturer = SmbiosMiscGetString (TokenToGet); + ManufacturerStrLen = StrLen(Manufacturer); + if (ManufacturerStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Token to get for Processor Version + // + TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_VERSION); + Version = SmbiosMiscGetString (TokenToGet); + VersionStrLen = StrLen(Version); + if (VersionStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Token to get for Serial Number + // + TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_SERIAL_NUMBER); + SerialNumber = SmbiosMiscGetString (TokenToGet); + SerialNumberStrLen = StrLen(SerialNumber); + if (SerialNumberStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Token to get for Assert Tag Information + // + TokenToGet = STRING_TOKEN (STR_MISC_ASSERT_TAG_DATA); + AssetTag = SmbiosMiscGetString (TokenToGet); + AssetTagStrLen = StrLen(AssetTag); + if (AssetTagStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Token to get for part number Information + // + TokenToGet = STRING_TOKEN (STR_MISC_PART_NUMBER); + PartNumber = SmbiosMiscGetString (TokenToGet); + PartNumberStrLen = StrLen(PartNumber); + if (PartNumberStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE4) + AssetTagStrLen + 1 + SocketStrLen + 1+ ManufacturerStrLen +1 + VersionStrLen+ 1+ SerialNumberStrLen + 1 + PartNumberStrLen+ 1 + 1); + + SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE4); + + // + // Make handle chosen by smbios protocol.add automatically. + // + SmbiosRecord->Hdr.Handle = 0; + + SmbiosRecord-> Socket= 1; + SmbiosRecord -> ProcessorManufacture = 2; + SmbiosRecord -> ProcessorVersion = 3; + SmbiosRecord ->SerialNumber =4; + + SmbiosRecord-> AssetTag= 5; + SmbiosRecord-> PartNumber= 6; + + // + // Processor Type + // + ForType4InputData-> VariableRecord.ProcessorType= EfiCentralProcessor; + SmbiosRecord -> ProcessorType = ForType4InputData-> VariableRecord.ProcessorType; + + // + // Processor Family + // + ForType4InputData-> VariableRecord.ProcessorFamily= EfiProcessorFamilyIntelAtomProcessor; //0x2B;; + SmbiosRecord -> ProcessorFamily = ForType4InputData-> VariableRecord.ProcessorFamily; + SmbiosRecord -> ExternalClock = DetermineiFsbFromMsr(); + + // + // Processor ID + // + AsmCpuid(0x001, &Eax01, &Ebx01, &Ecx01, &Edx01); + ProcessorId->Signature = *(PROCESSOR_SIGNATURE *)&Eax01; + ProcessorId->FeatureFlags = *(PROCESSOR_FEATURE_FLAGS *)&Edx01; + SmbiosRecord -> ProcessorId = *(PROCESSOR_ID_DATA *)ProcessorId; + + // + // Processor Voltage + // + ForType4InputData-> VariableRecord.ProcessorVoltage= *(EFI_PROCESSOR_VOLTAGE_DATA *)&ProcessorVoltage; + SmbiosRecord -> Voltage = *(PROCESSOR_VOLTAGE *) &(ForType4InputData-> VariableRecord.ProcessorVoltage); + + // + // Status + // + ForType4InputData-> VariableRecord.ProcessorHealthStatus= 0x41;//0x41; + SmbiosRecord -> Status = ForType4InputData-> VariableRecord.ProcessorHealthStatus; + + // + // Processor Upgrade + // + SmbiosRecord -> ProcessorUpgrade = 0x008; + + // + // Processor Family 2 + // + SmbiosRecord -> ProcessorFamily2 = ForType4InputData-> VariableRecord.ProcessorFamily; + + // + // Processor speed + // + SmbiosRecord-> CurrentSpeed = *(UINT16*) & Frequency; + SmbiosRecord-> MaxSpeed = *(UINT16*) & Frequency; + + // + // Processor Characteristics + // + AsmCpuid(0x8000000, NULL, NULL, NULL, &Edx01); + Edx01= Edx01 >> 28; + Edx01 &= 0x01; + SmbiosRecord-> ProcessorCharacteristics= (UINT16)Edx01; + + // + // Processor Core Count and Enabled core count + // + Status = gBS->LocateProtocol ( + &gEfiMpServiceProtocolGuid, + NULL, + (void **)&MpService + ); + if (!EFI_ERROR (Status)) { + // + // Determine the number of processors + // + MpService->GetNumberOfProcessors ( + MpService, + &NumberOfProcessors, + &NumberOfEnabledProcessors + ); + } + SmbiosRecord-> CoreCount= (UINT8)NumberOfProcessors; + SmbiosRecord-> EnabledCoreCount= (UINT8)NumberOfEnabledProcessors; + SmbiosRecord-> ThreadCount= (UINT8)NumberOfEnabledProcessors; + SmbiosRecord-> ProcessorCharacteristics = 0x2; // Unknown + + // + // Processor Cache Handle + // + GetCacheHandle( Smbios,1, &L1CacheHandle); + GetCacheHandle( Smbios,2, &L2CacheHandle); + GetCacheHandle( Smbios,3, &L3CacheHandle); + + // + // Updating Cache Handle Information + // + SmbiosRecord->L1CacheHandle = L1CacheHandle; + SmbiosRecord->L2CacheHandle = L2CacheHandle; + SmbiosRecord->L3CacheHandle = L3CacheHandle; + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(Socket, OptionalStrStart); + UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart + SocketStrLen + 1); + UnicodeStrToAsciiStr(Version, OptionalStrStart + SocketStrLen + 1 + ManufacturerStrLen+ 1); + UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + SocketStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1); + UnicodeStrToAsciiStr(AssetTag, OptionalStrStart + SerialNumberStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1 + SocketStrLen + 1); + UnicodeStrToAsciiStr(PartNumber, OptionalStrStart + SerialNumberStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1 + SocketStrLen + 1 + AssetTagStrLen + 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 + ); + if (EFI_ERROR (Status)) return Status; + FreePool(SmbiosRecord); + return Status; + +} + diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscResetCapabilitiesData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscResetCapabilitiesData.c new file mode 100644 index 0000000000..903a34d1b1 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscResetCapabilitiesData.c @@ -0,0 +1,48 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscResetCapabilitiesData.c + +Abstract: + + Static data of Reset Capabilities information. + Reset Capabilities information is Misc. subclass type 17 and SMBIOS type 23. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_RESET_CAPABILITIES, MiscResetCapabilities) += { + { // ResetCapabilities + 0, // Status + 0, // BootOption + 0, // BootOptionOnLimit + 0, // WatchdogTimerPresent + 0 // Reserved + }, + 0xFFFF, // ResetCount + 0xFFFF, // ResetLimit + 0xFFFF, // ResetTimerInterval + 0xFFFF // ResetTimeout +}; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscResetCapabilitiesFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscResetCapabilitiesFunction.c new file mode 100644 index 0000000000..1cf0f9023a --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscResetCapabilitiesFunction.c @@ -0,0 +1,90 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + MiscResetCapabilitiesFunction.c + +Abstract: + + ResetCapabilities. + SMBIOS type 23. + +--*/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.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(MiscResetCapabilities) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE23 *SmbiosRecord; + EFI_MISC_RESET_CAPABILITIES *ForType23InputData; + + ForType23InputData = (EFI_MISC_RESET_CAPABILITIES *)RecordData; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE23) + 1 + 1); + ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE23) + 1 + 1); + + SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_SYSTEM_RESET; + SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE23); + + // + // Make handle chosen by smbios protocol.add automatically. + // + SmbiosRecord->Hdr.Handle = 0; + SmbiosRecord->Capabilities = *(UINT8*)&(ForType23InputData->ResetCapabilities); + SmbiosRecord->ResetCount = (UINT16)ForType23InputData->ResetCount; + SmbiosRecord->ResetLimit = (UINT16)ForType23InputData->ResetLimit; + SmbiosRecord->TimerInterval = (UINT16)ForType23InputData->ResetTimerInterval; + SmbiosRecord->Timeout = (UINT16)ForType23InputData->ResetTimeout; + + // + // 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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriver.h b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriver.h new file mode 100644 index 0000000000..9e188c69a9 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriver.h @@ -0,0 +1,193 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscSubclassDriver.h + +Abstract: + + Header file for MiscSubclass Driver. + + +**/ + +#ifndef _MISC_SUBCLASS_DRIVER_H +#define _MISC_SUBCLASS_DRIVER_H + + +#include "CommonHeader.h" + +extern UINT8 MiscSubclassStrings[]; + + +#define T14_FVI_STRING "Driver/firmware version" +#define EFI_SMBIOS_TYPE_FIRMWARE_VERSION_INFO 0x90 +#define EFI_SMBIOS_TYPE_MISC_VERSION_INFO 0x94 +#define TOUCH_ACPI_ID "I2C05\\SFFFF\\400K" +#define TOUCH_RESET_GPIO_MMIO 0xFED0C508 +#define EFI_SMBIOS_TYPE_SEC_INFO 0x83 +#define IntelIdentifer 0x6F725076 + +// +// 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_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 \ + ) + +#pragma pack(1) + +// +// This is definition for SMBIOS Oem data type 0x90 +// +typedef struct { + STRING_REF SECVersion; + STRING_REF uCodeVersion; + STRING_REF GOPVersion; + STRING_REF CpuStepping; +} EFI_MISC_OEM_TYPE_0x90; + +// +// This is definition for SMBIOS Oem data type 0x90 +// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING SECVersion; + SMBIOS_TABLE_STRING uCodeVersion; + SMBIOS_TABLE_STRING GOPVersion; + SMBIOS_TABLE_STRING CpuStepping; +} SMBIOS_TABLE_TYPE90; + +typedef struct { + STRING_REF GopVersion; + STRING_REF UCodeVersion; + STRING_REF MRCVersion; + STRING_REF SECVersion; + STRING_REF ULPMCVersion; + STRING_REF PMCVersion; + STRING_REF PUnitVersion; + STRING_REF SoCVersion; + STRING_REF BoardVersion; + STRING_REF FabVersion; + STRING_REF CPUFlavor; + STRING_REF BiosVersion; + STRING_REF PmicVersion; + STRING_REF TouchVersion; + STRING_REF SecureBoot; + STRING_REF BootMode; + STRING_REF SpeedStepMode; + STRING_REF CPUTurboMode; + STRING_REF MaxCState; + STRING_REF GfxTurbo; + STRING_REF IdleReserve; + STRING_REF RC6; +}EFI_MISC_OEM_TYPE_0x94; + +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING GopVersion; + SMBIOS_TABLE_STRING uCodeVersion; + SMBIOS_TABLE_STRING MRCVersion; + SMBIOS_TABLE_STRING SECVersion; + SMBIOS_TABLE_STRING ULPMCVersion; + SMBIOS_TABLE_STRING PMCVersion; + SMBIOS_TABLE_STRING PUnitVersion; + SMBIOS_TABLE_STRING SoCVersion; + SMBIOS_TABLE_STRING BoardVersion; + SMBIOS_TABLE_STRING FabVersion; + SMBIOS_TABLE_STRING CPUFlavor; + SMBIOS_TABLE_STRING BiosVersion; + SMBIOS_TABLE_STRING PmicVersion; + SMBIOS_TABLE_STRING TouchVersion; + SMBIOS_TABLE_STRING SecureBoot; + SMBIOS_TABLE_STRING BootMode; + SMBIOS_TABLE_STRING SpeedStepMode; + SMBIOS_TABLE_STRING CPUTurboMode; + SMBIOS_TABLE_STRING MaxCState; + SMBIOS_TABLE_STRING GfxTurbo; + SMBIOS_TABLE_STRING IdleReserve; + SMBIOS_TABLE_STRING RC6; +}SMBIOS_TABLE_TYPE94; + +#pragma pack() +// +// Data Table Array +// +extern EFI_MISC_SMBIOS_DATA_TABLE mMiscSubclassDataTable[]; + +// +// Data Table Array Entries +// +extern UINTN mMiscSubclassDataTableEntries; +extern EFI_HII_HANDLE mHiiHandle; + +// +// Prototypes +// +EFI_STATUS +EFIAPI +MiscSubclassDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STRING +EFIAPI +SmbiosMiscGetString ( + IN EFI_STRING_ID StringId + ); + +#endif diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriver.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriver.uni new file mode 100644 index 0000000000000000000000000000000000000000..2d0d1415d329f7e51d452321a422b36076cb4924 GIT binary patch literal 2354 zcmbuATW`}q6ok(+692(UU!b%NAf75fYA!%T8&^q6;i<~4sinq2b`r>+2fo>j?M)G) zP*wHb&d!;gGrRfuqi%JJY~P;o_t+jWs+VnKOx!tbb2pk=&fd({d?!S{wubfWZNO>( zlZ2=U+zh;#!=5u9f<2*K5;1k-F>Dt$CsJ!0_NBx}%!rNhB=l}UD^4$z%q9 zjD%a@YxiWEVNE{)VQ3@1%DQqagk3T5x#o^_fg)z&o0PifObfdX_BE_;EykxiTq>^L zoEBrgVz+zR1U5pH8eT8u${Fj_BY1}Oh)lYQ|1~SVHe&sqsJpComGNqBh#GD8FSZ(p z(=t$24q8%+W9Kt@%d4yS%xQhZ`7(aKFmnI&eszV1)w~6RGq3oP#>g&->N#dz<~yJYBX-$)jKp1Y$~hobG0N(r-Vv+pUuZwFBIde- z?QIr+ine_&aVqoL7xT0ob z_6!;4>Jy2XVPfTom}sY-U{7nx&4s3s|Gbx*P7g% z(aEA*VfVV8%P zbkRw-d<7G|x*-?os2Z-^DHL6(-f(rD!el`&WBrUaCGwh9mD8;btL<_3Ty6e@sS4zr zL|RQ;{R*%AeRmTbz1O7a!`Z~Jn4_3>l( zTK!t-S2g8t>Qt6Tg`a~za}mpb)UA)lD#k}>!@7BY) T^-)vazpG#ITKHG0x(~kqOyzWd literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriverDataTable.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriverDataTable.c new file mode 100644 index 0000000000..3b77a75443 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriverDataTable.c @@ -0,0 +1,103 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscSubclassDriverDataTable.c + +Abstract: + + Create the mMiscSubclassDataTable structure, and it is used to report + any generate data to the DataHub. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +// +// External definitions referenced by Data Table entries. +// +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_BIOS_VENDOR_DATA, MiscBiosVendor, MiscBiosVendor); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_MANUFACTURER_DATA, MiscSystemManufacturer, MiscSystemManufacturer); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_BASE_BOARD_MANUFACTURER_DATA, MiscBaseBoardManufacturer, MiscBaseBoardManufacturer); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_CHASSIS_MANUFACTURER_DATA, MiscChassisManufacturer, MiscChassisManufacturer); +MISC_SMBIOS_TABLE_EXTERNS(EFI_CACHE_VARIABLE_RECORD, MiscProcessorCache, MiscProcessorCache); //type 7 +MISC_SMBIOS_TABLE_EXTERNS(EFI_CPU_DATA_RECORD, MiscProcessorInformation, MiscProcessorInformation); //type 4 +MISC_SMBIOS_TABLE_EXTERNS(EFI_MEMORY_ARRAY_LOCATION_DATA, MiscPhysicalMemoryArray,MiscPhysicalMemoryArray); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MEMORY_ARRAY_LINK_DATA, MiscMemoryDevice, MiscMemoryDevice); + +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortIde1, MiscPortInternalConnectorDesignator); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortIde2, MiscPortInternalConnectorDesignator); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortAtxPower, MiscPortInternalConnectorDesignator); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCIEx16Slot1, MiscSystemSlotDesignation); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCIEx16Slot2, MiscSystemSlotDesignation); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCIEx4, MiscSystemSlotDesignation); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCIEx1Slot1, MiscSystemSlotDesignation); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCIEx1Slot2, MiscSystemSlotDesignation); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCIEx1Slot3, MiscSystemSlotDesignation); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCI1, MiscSystemSlotDesignation); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCI2, MiscSystemSlotDesignation); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCI3, MiscSystemSlotDesignation); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_ONBOARD_DEVICE_DATA, MiscOnboardDeviceVideo, MiscOnboardDevice); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_ONBOARD_DEVICE_DATA, MiscOnboardDeviceNetwork, MiscOnboardDevice); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_ONBOARD_DEVICE_DATA, MiscOnboardDeviceAudio, MiscOnboardDevice); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES_DATA, NumberOfInstallableLanguages, NumberOfInstallableLanguages); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_SYSTEM_LANGUAGE_STRING_DATA, SystemLanguageString, SystemLanguageString); +MISC_SMBIOS_TABLE_EXTERNS(EFI_MISC_BOOT_INFORMATION_STATUS_DATA, BootInformationStatus, BootInformationStatus); + +// +// Data Table. +// +EFI_MISC_SMBIOS_DATA_TABLE mMiscSubclassDataTable[] = { + 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(MiscProcessorCache, MiscProcessorCache), //type 7 + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscProcessorInformation, MiscProcessorInformation), //type 4 + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPhysicalMemoryArray, MiscPhysicalMemoryArray), //Type 16 + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscMemoryDevice, MiscMemoryDevice), //Type 17 + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortIde1, MiscPortInternalConnectorDesignator), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortIde2, MiscPortInternalConnectorDesignator), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscPortAtxPower, MiscPortInternalConnectorDesignator), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlotPCIEx16Slot1, MiscSystemSlotDesignation), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlotPCIEx16Slot2, MiscSystemSlotDesignation), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlotPCIEx4, MiscSystemSlotDesignation), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlotPCIEx1Slot1, MiscSystemSlotDesignation), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlotPCIEx1Slot2, MiscSystemSlotDesignation), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlotPCIEx1Slot3, MiscSystemSlotDesignation), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlotPCI1, MiscSystemSlotDesignation), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlotPCI2, MiscSystemSlotDesignation), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscSystemSlotPCI3, MiscSystemSlotDesignation), +#if defined( ALWAYS_DISABLE_ONBOARD_VIDEO ) && \ + ( ALWAYS_DISABLE_ONBOARD_VIDEO != 0 ) + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscOnboardDeviceNetwork, MiscOnboardDevice), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscOnboardDeviceAudio, MiscOnboardDevice), +#else + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscOnboardDeviceVideo, MiscOnboardDevice), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(MiscOnboardDeviceAudio, MiscOnboardDevice), +#endif + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(SystemLanguageString, SystemLanguageString), + MISC_SMBIOS_TABLE_ENTRY_DATA_AND_FUNCTION(BootInformationStatus, BootInformationStatus), +}; + +// +// Number of Data Table entries. +// +UINTN mMiscSubclassDataTableEntries = + (sizeof mMiscSubclassDataTable) / sizeof(EFI_MISC_SMBIOS_DATA_TABLE); diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriverEntryPoint.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriverEntryPoint.c new file mode 100644 index 0000000000..cae5a8e38a --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSubclassDriverEntryPoint.c @@ -0,0 +1,174 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscSubclassDriverEntryPoint.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" +#include + +EFI_HII_HANDLE mHiiHandle; +EFI_HII_STRING_PROTOCOL *mHiiString; + + +EFI_STRING +EFIAPI +SmbiosMiscGetString ( + IN EFI_STRING_ID StringId + ){ + + EFI_STATUS Status; + UINTN StringSize; + CHAR16 TempString; + EFI_STRING String; + String = NULL; + + // + // Retrieve the size of the string in the string package for the BestLanguage + // + StringSize = 0; + Status = mHiiString->GetString ( + mHiiString, + "en-US", + mHiiHandle, + StringId, + &TempString, + &StringSize, + NULL + ); + // + // If GetString() returns EFI_SUCCESS for a zero size, + // then there are no supported languages registered for HiiHandle. If GetString() + // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present + // in the HII Database + // + if (Status != EFI_BUFFER_TOO_SMALL) { + goto Error; + } + + // + // Allocate a buffer for the return string + // + String = AllocateZeroPool (StringSize); + if (String == NULL) { + goto Error; + } + + // + // Retrieve the string from the string package + // + Status = mHiiString->GetString ( + mHiiString, + "en-US", + mHiiHandle, + StringId, + String, + &StringSize, + NULL + ); + if (EFI_ERROR (Status)) { + // + // Free the buffer and return NULL if the supported languages can not be retrieved. + // + FreePool (String); + String = NULL; + } +Error: + + return String; +} + +/** + Standard EFI driver point. This driver parses the mMiscSubclassDataTable + structure and reports any generated data to the DataHub. + + @param ImageHandle - Handle for the image of this driver + @param SystemTable - Pointer to the EFI System Table + + @retval EFI_SUCCESS - The data was successfully reported to the Data Hub. + @retval EFI_DEVICE_ERROR - Can not locate any protocols + +**/ +EFI_STATUS +EFIAPI +MiscSubclassDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINTN Index; + EFI_STATUS EfiStatus; + EFI_SMBIOS_PROTOCOL *Smbios; + + // + // Retrieve the pointer to the UEFI HII String Protocol + // + EfiStatus = gBS->LocateProtocol ( + &gEfiHiiStringProtocolGuid, + NULL, + (VOID **) &mHiiString + ); + ASSERT_EFI_ERROR (EfiStatus); + + 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, + NULL, + MiscSubclassStrings, + NULL + ); + ASSERT (mHiiHandle != NULL); + + for (Index = 0; Index < mMiscSubclassDataTableEntries; ++Index) { + // + // If the entry have a function pointer, just log the data. + // + if (mMiscSubclassDataTable[Index].Function != NULL) { + EfiStatus = (*mMiscSubclassDataTable[Index].Function)( + mMiscSubclassDataTable[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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemLanguageString.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemLanguageString.uni new file mode 100644 index 0000000000000000000000000000000000000000..763a11f4673347fa209be4bdc72d5f376b260a0b GIT binary patch literal 1576 zcmZ{kTW=FF5QXO%iT_}wFHqV95Kk2#rR`E8a;ef(rB79JX}VG_Xp3%?Pl~kwt+>5VGC#dwZ-TXQM#3%d zb$Xg-c*agaxVJH*vOYNrVOLCIuBEdsP{d4p)3PqQ)7l?Vy%rNj zvD?3G3L7D+8nIr=wZYe|$MCH8Bbe$c{txWL-iY-tqW)#IUzu3V9Z}=_{5r3JIBjc{ zm4deP;>2|(ZN=&;KJ!{Pxqn87S}>?rf5XZc?o-sZztaTek$+W_${N{MOW<{hf(CZM z*tQ;ihpGnZs(Hj}2aR20C0^@m>oX^;t0obl>O%)jCq!I1@&HR(*4SVcu237yr|!!; zs2V-T_q@1J6Fh6L+mC=ZILvC~J)RLaegiGJj)7%=HG7JWISq zV&6-g3cW)uE>V_pp7YX*x)pOMR|1i1YA;<#A$|I~#5yS>sxyK8p6hG^$DQkKMs$}m zdV5dIbIx9&1nE#~P1j3WqSZ6Ez3+;ZzPGiU^(bYnXA3ah&lfz`gX=54{`f7bm{-;i ze$Re~7!&AMd^u9*?mrxk(dJ?P{S;Qj`(y`h$vY@n>Fc3)F8v>)1a+lBA5;zLdxNGM zwR6R*jbE>*+B@njb)DHA<1K$FxQEwuO + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscSystemLanguageStringData.c + +Abstract: + + Static data of System language string information. + System language string information is Misc. subclass type 12 and SMBIOS type 13. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_LANGUAGE_STRING_DATA, SystemLanguageString) += { + 0, + STRING_TOKEN(STR_MISC_SYSTEM_LANGUAGE_EN_US) +}; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemLanguageStringFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemLanguageStringFunction.c new file mode 100644 index 0000000000..c4494c3f65 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemLanguageStringFunction.c @@ -0,0 +1,98 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + MiscResetCapabilitiesFunction.c + +Abstract: + + ResetCapabilities. + SMBIOS type 23. + +--*/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.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(SystemLanguageString) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE13 *SmbiosRecord; + UINTN StrLeng; + CHAR8 *OptionalStrStart; + EFI_STRING Str; + STRING_REF TokenToGet; + + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_LANGUAGE_EN_US); + Str = SmbiosMiscGetString (TokenToGet); + StrLeng = StrLen(Str); + if (StrLeng > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + // Two zeros following the last string. + // + SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE13) + StrLeng + 1 + 1); + ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE13) + StrLeng + 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 = 1; + SmbiosRecord->Flags = 1; + SmbiosRecord->CurrentLanguages = 1; + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(Str, 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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemManufacturer.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemManufacturer.uni new file mode 100644 index 0000000000000000000000000000000000000000..cf563c8d2117465b44c7ff8d23e3352101efbf38 GIT binary patch literal 2478 zcmcJQTW?ZP5QXR2#Q$(YU$nMhjZcl50HsRGrJ>N;r>0y=i3JRtR{8Vlw`K$T(9{H* z7{b2JUbFVhntgu%Dp|1;*{1g07B;hy4ei!aY+qT=Uemv`xBT8S z+F#BNnC&sH+62pi-7yxz3=Fl`td1B>EYD7neOW~8xz7eR=j_ZLX!}@xu#&axQ-)O= zCL^p8aA)8R9ed3D8tguOip9X^J=jidjHUJ#oSR^uup&0{Gh%cH+UoW~nfd8E_Iiva z&Pcc`e4XwuJv=ZTfpBeIT6w*97Q&89g0Hc&UZIGY_>R_b(VeDtlQ~ziGdp5l+u#zp z{_t4zXvJ>xwj)-MS0UY(5fGT*d!}osb)`{)yFNR-2It(Oh8FU7nvV zV<1jxCbCjcN-hpvXVO-PuIy(X>pb_Lk)Z+%veBQj(uI2;wQcU?LAm80V-iPg`(hP% zouZ(oeWop1oq3h0Cd5^Jo7E~B>oBT#tUK1AuduF|1caD}Dw?ifapuTPM$)p{9KCRb znxilIT(i9ly9@S(+H{YJU0~I6W)0S>pbDeu-doJXU2F2$##T1+8mx}7mG?{f6L!R0 zHCS1C3Ad=&*ELQ=uM&$>lqH`>RN5+Tt3Fw;Bv?*~y>uakG|20i(c#)6o=MoRyUu!W zT)5r_Sl2l-0pZ4VntH}nBY8#>>?1-P6+P$DtF)bF{AIbxW7bp9<5Rv8{7hgVjfEE= zyhqVv9JRRLgWn_AB;+hqk4`WC!et+Q?k?X@VFkR8w&Nqsc8H-OG4vNiwXPc2M-9qM zj$CL@8lR)EN2lzT;7rLeMH(O&YGitEhku8WQx)0bK8xQ?W0{UVEd*bF_Z zSsr3ihJ&i|o<60YF4^p?-;nK?gz7tjfp}b@9#x_0a$6?noT%}uaKm%g>jh_ve1BBi zHAZdjshX)jljAwqEut4{D=>@gHqjEBkgb1>k7`?QknX7Hbht&y*S3vMo7}|LS6?I5 zslHfUl&aSx4_^M+(K+L7={&(LL};7n{BMR*xhkQCLLMt@JGCqRdhb`?@${M5e45Dt U*xP0^FlmreeSf?3Q~L&+KWpi7x&QzG literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemManufacturerData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemManufacturerData.c new file mode 100644 index 0000000000..055eb29b13 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemManufacturerData.c @@ -0,0 +1,53 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscSystemManufacturerData.c + +Abstract: + + Static data of System manufacturer information. + System manufacturer information is Misc. subclass type 3 and SMBIOS type 1. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) System Manufacturer data. +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_MANUFACTURER_DATA, 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 + // + // Undefined GUID but can be programmed later. + //0xFFFFFFFF, 0xFFFF, 0xFFFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + + // Undefined GUID that cannot be programmed later. + //0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + // TODO Hard code here for WHCT test. + 0xa5000288, 0x6462, 0x4524, 0x98, 0x6a, 0x9b, 0x77, 0x37, 0xe3, 0x15, 0xcf + // + }, + EfiSystemWakeupTypePowerSwitch // SystemWakeupType +}; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemManufacturerFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemManufacturerFunction.c new file mode 100644 index 0000000000..ff08b5b52f --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemManufacturerFunction.c @@ -0,0 +1,353 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscSystemManufacturerFunction.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data. + +--*/ + + +#include "CommonHeader.h" +#include "MiscSubclassDriver.h" +#include +#include +#include "Library/DebugLib.h" +#include + +/** + + Publish the smbios type 1. + + @param Event Event whose notification function is being invoked (gEfiDxeSmmReadyToLockProtocolGuid). + @param Context Pointer to the notification functions context, which is implementation dependent. + + @retval None + +**/ +EFI_STATUS +EFIAPI +AddSmbiosManuCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + + CHAR8 *OptionalStrStart; + UINTN ManuStrLen; + UINTN VerStrLen; + UINTN PdNameStrLen; + UINTN SerialNumStrLen; + UINTN SkuNumberStrLen; + UINTN FamilyNameStrLen; + EFI_STATUS Status; + EFI_STRING Manufacturer; + EFI_STRING ProductName; + EFI_STRING Version; + EFI_STRING SerialNumber; + EFI_STRING SkuNumber; + EFI_STRING FamilyName; + STRING_REF TokenToGet; + EFI_SMBIOS_HANDLE SmbiosHandle; + SMBIOS_TABLE_TYPE1 *SmbiosRecord; + EFI_MISC_SYSTEM_MANUFACTURER *ForType1InputData; + EFI_SMBIOS_PROTOCOL *Smbios; + CHAR16 Buffer[40]; + + CHAR16 *MacStr; + EFI_HANDLE *Handles; + UINTN BufferSize; + + ForType1InputData = (EFI_MISC_SYSTEM_MANUFACTURER *)Context; + + // + // First check for invalid parameters. + // + if (Context == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID *) &Smbios); + ASSERT_EFI_ERROR (Status); + + // + // Silicon Steppings + // + switch (PchStepping()) { + case PchA0: + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"MinnowBoard MAX A0 PLATFORM"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL); + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"A0"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL); + DEBUG ((EFI_D_ERROR, "A0 Stepping Detected\n")); + break; + case PchA1: + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"MinnowBoard MAX A1 PLATFORM"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL); + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"A1"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL); + DEBUG ((EFI_D_ERROR, "A1 Stepping Detected\n")); + break; + case PchB0: + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"MinnowBoard MAX B0 PLATFORM"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL); + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"B0"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL); + DEBUG ((EFI_D_ERROR, "B0 Stepping Detected\n")); + break; + case PchB1: + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"MinnowBoard MAX B1 PLATFORM"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL); + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"B1"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL); + DEBUG ((EFI_D_ERROR, "B1 Stepping Detected\n")); + break; + case PchB2: + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"MinnowBoard MAX B2 PLATFORM"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL); + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"B2"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL); + DEBUG ((EFI_D_ERROR, "B2 Stepping Detected\n")); + break; + case PchB3: + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"MinnowBoard MAX B3 PLATFORM"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL); + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"B3"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL); + DEBUG ((EFI_D_ERROR, "B3 Stepping Detected\n")); + break; + case PchC0: + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"MinnowBoard MAX C0 PLATFORM"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL); + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"C0"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL); + DEBUG ((EFI_D_ERROR, "C0 Stepping Detected\n")); + break; + case PchD0: + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"MinnowBoard MAX D0 PLATFORM"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL); + UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"D0"); + HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL); + DEBUG ((EFI_D_ERROR, "D0 Stepping Detected\n")); + break; + default: + DEBUG ((EFI_D_ERROR, "Unknow Stepping Detected\n")); + break; + } + + + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_MANUFACTURER); + Manufacturer = SmbiosMiscGetString (TokenToGet); + ManuStrLen = StrLen(Manufacturer); + if (ManuStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_PRODUCT_NAME); + ProductName = SmbiosMiscGetString (TokenToGet); + PdNameStrLen = StrLen(ProductName); + if (PdNameStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_VERSION); + Version = SmbiosMiscGetString (TokenToGet); + VerStrLen = StrLen(Version); + if (VerStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + + // + //Get handle infomation + // + BufferSize = 0; + Handles = NULL; + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiSimpleNetworkProtocolGuid, + NULL, + &BufferSize, + Handles + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + Handles = AllocateZeroPool(BufferSize); + if (Handles == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + Status = gBS->LocateHandle( + ByProtocol, + &gEfiSimpleNetworkProtocolGuid, + NULL, + &BufferSize, + Handles + ); + } + + // + //Get the MAC string + // + Status = NetLibGetMacString ( + *Handles, + NULL, + &MacStr + ); + if (EFI_ERROR (Status)) { + return Status; + } + SerialNumber = MacStr; + SerialNumStrLen = StrLen(SerialNumber); + if (SerialNumStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SKU_NUMBER); + SkuNumber = SmbiosMiscGetString (TokenToGet); + SkuNumberStrLen = StrLen(SkuNumber); + if (SkuNumberStrLen > SMBIOS_STRING_MAX_LENGTH) { + return EFI_UNSUPPORTED; + } + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_FAMILY_NAME1); + FamilyName = SmbiosMiscGetString (TokenToGet); + FamilyNameStrLen = StrLen(FamilyName); + if (FamilyNameStrLen > 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 + SkuNumberStrLen + 1 + FamilyNameStrLen + 1 + 1); + ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE1) + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + SkuNumberStrLen + 1 + FamilyNameStrLen + 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; + + // + // Version will be the 4th optional string following the formatted structure. + // + SmbiosRecord->SerialNumber = 4; + + SmbiosRecord->SKUNumber= 5; + SmbiosRecord->Family= 6; + + // + // Unique UUID + // + ForType1InputData->SystemUuid.Data1 = PcdGet32 (PcdProductSerialNumber); + ForType1InputData->SystemUuid.Data4[0] = PcdGet8 (PcdEmmcManufacturerId); + + CopyMem ((UINT8 *) (&SmbiosRecord->Uuid),&ForType1InputData->SystemUuid,16); + + SmbiosRecord->WakeUpType = (UINT8)ForType1InputData->SystemWakeupType; + + OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); + UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart); + UnicodeStrToAsciiStr(ProductName, OptionalStrStart + ManuStrLen + 1); + UnicodeStrToAsciiStr(Version, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1); + UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1); + + UnicodeStrToAsciiStr(SkuNumber, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1); + UnicodeStrToAsciiStr(FamilyName, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + SkuNumberStrLen +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; +} + +/** + 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) +{ + EFI_STATUS Status; + static BOOLEAN CallbackIsInstalledManu = FALSE; + VOID *AddSmbiosManuCallbackNotifyReg; + EFI_EVENT AddSmbiosManuCallbackEvent; + + + if (CallbackIsInstalledManu == FALSE) { + CallbackIsInstalledManu = TRUE; // Prevent more than 1 callback. + DEBUG ((EFI_D_INFO, "Create Smbios Manu callback.\n")); + + // + // gEfiDxeSmmReadyToLockProtocolGuid is ready + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + (EFI_EVENT_NOTIFY)AddSmbiosManuCallback, + RecordData, + &AddSmbiosManuCallbackEvent + ); + + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + + } + + Status = gBS->RegisterProtocolNotify ( + &gEfiDxeSmmReadyToLockProtocolGuid, + AddSmbiosManuCallbackEvent, + &AddSmbiosManuCallbackNotifyReg + ); + + return Status; + } + + return EFI_SUCCESS; + +} diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemOptionString.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemOptionString.uni new file mode 100644 index 0000000000000000000000000000000000000000..696887a192cf10650f0b828d4e24cba105ee3248 GIT binary patch literal 1578 zcmZ{kTW=FF6ok(+692(UUubC(Ks;4|l(Y-1AlWKORr(a=)^w#@&?Xe}=YenRy@iXS z*gp30obh$F?DJVJpT$$iPrLVK!y7u@);G)|F9V?|ihd9eXo-q@9!b#=17JcQsZcn51Mm za5M0h9(zqZ0eeorCu8B`8Em(_%!rNZq>NUe6{ifg)z&o0huhOk2CJ?d#gmu82P$ajCd|_gc(o z#qRjDDQtu&HG*EMwIkN4r|_)bhcoFa{`aheyAkUjWc|tNSec;afvjo1f17I{PWzg& za?qZ;xbQxcw}QIL&%D+x&Yy8ZZ5Y(m-!U_V`y96&ue3mU;9qG{jYjs-B6wZnpu|4V zcC1GnqpCw!^&@6uJa)q<@><_mpFUz`yy7*t^-zWRVj+%>0~BXX6asv+w=xvG9g|A`eb*BgxTD&Z87 zeJOD&^cXF!ah7Uc@zM(2ir$qoj?69E%NKG;pL<<1x+pWMJ&yIB_t^}N2k*B9*$H=4 z_-)8Y9@JZGd9S1;QoU-&-??(-?R~9YJxdkqmE_i{mV>ii+>$yI+QmOB4VZuQtiu<| zaYNy)$d8BrRBqzNv;2!G1%e81?Zl51os`w}z0k{+pmQNm3Y&KNV-XD-x`Iu(mTgJT|lGtqZm`%iODzX7cs>umr4 literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemOptionStringData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemOptionStringData.c new file mode 100644 index 0000000000..8fbaa8a148 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemOptionStringData.c @@ -0,0 +1,36 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscSystemOptionStringData.c + +Abstract: + + Static data of System option string. + System option string is Miscellaneous subclass type: 10 and SMBIOS type: 13. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_OPTION_STRING_DATA, SystemOptionString) += { STRING_TOKEN(STR_MISC_SYSTEM_OPTION_EN_US) }; diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemOptionStringFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemOptionStringFunction.c new file mode 100644 index 0000000000..414afd3abc --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemOptionStringFunction.c @@ -0,0 +1,98 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscSystemOptionStringFunction.c + +Abstract: + + BIOS system option string boot time changes. + SMBIOS type 12. + +--*/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.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; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_OPTION_EN_US); + OptionString = SmbiosMiscGetString (TokenToGet); + 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/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemSlotDesignation.uni b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemSlotDesignation.uni new file mode 100644 index 0000000000000000000000000000000000000000..d5470b6fb0f50a7731191c2d5f455e88497d3264 GIT binary patch literal 2920 zcmcJR-A_|N5XI-&#Q$MaUKD`}7$1n5@KLo9C}~T8r-pt|ZbDnr7PSAo`a8Sbd$%Sg zg4f)zJG(n`=G>XHxBUE3wW>K=w^uyR?HQ|TK07?Vmju$CRMK3?Hc zaQ)_M(PI?5)wj)HBScjr)JwT$to7Dic&7burn-v%4JV;DV*MSj-&w6zCRB5QS9cjd zS=K7+_w|fb*k#9tL8Slbu@O4Rr9qzw^QaC`>IJmDEd%G(=|L=9=U-fEo-bW z3syqccbDf@L$h0*ZYo2{rZR zI1zK*!P+uQc#E1{<~Rjrgei3wQvK%kXz3)3O)k@*>Bx~xWylFm1mXOhbJ4V$~ zR=D@!D^zeUtS0OpJp16|=v25fieCI7_a>@bUw%1-74Y8MnzyuCgNyF{(0?~{!=?O9 zG@yP|=zz|o>=|mV__#G+JKfdr%?euWP+e*2&^nA){7JVbeszp8+E{0ts;if_ZEwL3 zPr>0HE<+fsvJj6L>GIeX3K43#oH{TQtAFF2&5Me9Ob62%m38xC$0DD%td7M_ M{TrLusrXy)3*L6AXaE2J literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemSlotDesignationData.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemSlotDesignationData.c new file mode 100644 index 0000000000..17e69c2e3d --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemSlotDesignationData.c @@ -0,0 +1,251 @@ +/** @file + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscSystemSlotDesignationData.c + +Abstract: + + Static data of System Slot Designation. + System Slot Designation is Misc. subclass type 7 and SMBIOS type 9. + + +**/ + + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCIEx16Slot1) = { + STRING_TOKEN(STR_MISC_SYSTEM_SLOT_PCIEX16_1), // SlotDesignation + EfiSlotTypePciExpress, // SlotType + EfiSlotDataBusWidth16xOrx16, // SlotDataBusWidth + EfiSlotUsageAvailable, // SlotUsage + EfiSlotLengthShort, // SlotLength + 0x06, // 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; + 0, // PmeSignalSupported :1; + 0, // HotPlugDevicesSupported :1; + 0, // SmbusSignalSupported :1; + 0 // Reserved :21; + }, + 0 // SlotDevicePath +}; + +MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCIEx16Slot2) = { + STRING_TOKEN(STR_MISC_SYSTEM_SLOT_PCIEX16_2), // SlotDesignation + EfiSlotTypePciExpress, // SlotType + EfiSlotDataBusWidth16xOrx16, // SlotDataBusWidth + EfiSlotUsageAvailable, // SlotUsage + EfiSlotLengthShort, // SlotLength + 0x04, // 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; + 0, // PmeSignalSupported :1; + 0, // HotPlugDevicesSupported :1; + 0, // SmbusSignalSupported :1; + 0 // Reserved :21; + }, + 0 // SlotDevicePath +}; + +MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCIEx4) = { + STRING_TOKEN(STR_MISC_SYSTEM_SLOT_PCIEX4), // SlotDesignation + EfiSlotTypePciExpress, // SlotType + EfiSlotDataBusWidth4xOrx4, // SlotDataBusWidth + EfiSlotUsageAvailable, // SlotUsage + EfiSlotLengthShort, // SlotLength + 0x03, // 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; + 0, // PmeSignalSupported :1; + 0, // HotPlugDevicesSupported :1; + 0, // SmbusSignalSupported :1; + 0 // Reserved :21; + }, + 0 // SlotDevicePath +}; + +MISC_SMBIOS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotPCIEx1Slot1) = { + STRING_TOKEN(STR_MISC_SYSTEM_SLOT_PCIEX1_1), // SlotDesignation + EfiSlotTypePciExpress, // SlotType + EfiSlotDataBusWidth1xOrx1, // SlotDataBusWidth + EfiSlotUsageAvailable, // SlotUsage + EfiSlotLengthShort, // SlotLength + 0x02, // 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_DATA, MiscSystemSlotPCIEx1Slot2) = { + STRING_TOKEN(STR_MISC_SYSTEM_SLOT_PCIEX1_2), // SlotDesignation + EfiSlotTypePciExpress, // SlotType + EfiSlotDataBusWidth1xOrx1, // SlotDataBusWidth + EfiSlotUsageAvailable, // SlotUsage + EfiSlotLengthShort, // SlotLength + 0x15, // 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_DATA, MiscSystemSlotPCIEx1Slot3) = { + STRING_TOKEN(STR_MISC_SYSTEM_SLOT_PCIEX1_3), // SlotDesignation + EfiSlotTypePciExpress, // SlotType + EfiSlotDataBusWidth1xOrx1, // SlotDataBusWidth + EfiSlotUsageAvailable, // SlotUsage + EfiSlotLengthShort, // SlotLength + 0x16, // 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_DATA, MiscSystemSlotPCI1) = { + STRING_TOKEN(STR_MISC_SYSTEM_SLOT_PCI1), // SlotDesignation + EfiSlotTypePci, // SlotType + EfiSlotDataBusWidth32Bit, // SlotDataBusWidth + EfiSlotUsageAvailable, // SlotUsage + EfiSlotLengthLong , // SlotLength + 0x07, // 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_DATA, MiscSystemSlotPCI2) = { + STRING_TOKEN(STR_MISC_SYSTEM_SLOT_PCI2), // SlotDesignation + EfiSlotTypePci, // SlotType + EfiSlotDataBusWidth32Bit, // SlotDataBusWidth + EfiSlotUsageAvailable, // SlotUsage + EfiSlotLengthLong , // SlotLength + 0x18, // 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_DATA, MiscSystemSlotPCI3) = { + STRING_TOKEN(STR_MISC_SYSTEM_SLOT_PCI3), // SlotDesignation + EfiSlotTypePci, // SlotType + EfiSlotDataBusWidth32Bit, // SlotDataBusWidth + EfiSlotUsageAvailable, // SlotUsage + EfiSlotLengthLong , // SlotLength + 0x17, // 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 +}; + diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemSlotDesignationFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemSlotDesignationFunction.c new file mode 100644 index 0000000000..30be4adac4 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscSystemSlotDesignationFunction.c @@ -0,0 +1,132 @@ +/*++ + +Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscSystemSlotDesignatorFunction.c + +Abstract: + + BIOS system slot designator information boot time changes. + SMBIOS type 9. + +--*/ + +#include "MiscSubclassDriver.h" + +/** + 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(MiscSystemSlotDesignation) +{ + CHAR8 *OptionalStrStart; + UINTN SlotDesignationStrLen; + EFI_STATUS Status; + EFI_STRING SlotDesignation; + STRING_REF TokenToGet; + SMBIOS_TABLE_TYPE9 *SmbiosRecord; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_MISC_SYSTEM_SLOT_DESIGNATION* ForType9InputData; + + ForType9InputData = (EFI_MISC_SYSTEM_SLOT_DESIGNATION *)RecordData; + + // + // First check for invalid parameters. + // + if (RecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + + TokenToGet = 0; + switch (ForType9InputData->SlotDesignation) { + case STR_MISC_SYSTEM_SLOT_PCIEX16_1: + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_PCIEX16_1); + break; + case STR_MISC_SYSTEM_SLOT_PCIEX16_2: + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_PCIEX16_2); + break; + case STR_MISC_SYSTEM_SLOT_PCIEX4: + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_PCIEX4); + break; + case STR_MISC_SYSTEM_SLOT_PCIEX1_1: + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_PCIEX1_1); + break; + case STR_MISC_SYSTEM_SLOT_PCIEX1_2: + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_PCIEX1_2); + break; + case STR_MISC_SYSTEM_SLOT_PCIEX1_3: + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_PCIEX1_3); + break; + case STR_MISC_SYSTEM_SLOT_PCI1: + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_PCI1); + break; + case STR_MISC_SYSTEM_SLOT_PCI2: + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_PCI2); + break; + case STR_MISC_SYSTEM_SLOT_PCI3: + TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SLOT_PCI3); + break; + default: + break; + } + + SlotDesignation = SmbiosMiscGetString (TokenToGet); + 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 = (UINT8)ForType9InputData->SlotType; + SmbiosRecord->SlotDataBusWidth = (UINT8)ForType9InputData->SlotDataBusWidth; + SmbiosRecord->CurrentUsage = (UINT8)ForType9InputData->SlotUsage; + SmbiosRecord->SlotLength = (UINT8)ForType9InputData->SlotLength; + SmbiosRecord->SlotID = ForType9InputData->SlotId; + + // + // Slot Characteristics + // + CopyMem ((UINT8 *) &SmbiosRecord->SlotCharacteristics1,(UINT8 *) &ForType9InputData->SlotCharacteristics,2); + 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/Vlv2TbltDevicePkg/SmBiosMiscDxe/SmBiosMiscDxe.inf b/Vlv2TbltDevicePkg/SmBiosMiscDxe/SmBiosMiscDxe.inf new file mode 100644 index 0000000000..842dda3600 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/SmBiosMiscDxe.inf @@ -0,0 +1,144 @@ +## @file +# Component name for module MiscSubclass +# +# FIX ME! +# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MiscSubclass + FILE_GUID = 4EFFB560-B28B-4e57-9DAD-4344E32EA3BA + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = MiscSubclassDriverEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + MiscBaseBoardManufacturer.uni + MiscBaseBoardManufacturerData.c + MiscBaseBoardManufacturerFunction.c + MiscBiosVendor.uni + MiscBiosVendorData.c + MiscBiosVendorFunction.c + MiscBootInformationData.c + MiscBootInformationFunction.c + MiscChassisManufacturer.uni + MiscChassisManufacturerData.c + MiscChassisManufacturerFunction.c + MiscNumberOfInstallableLanguagesData.c + MiscNumberOfInstallableLanguagesFunction.c + MiscOemString.uni + MiscOemStringData.c + MiscOemStringFunction.c + MiscOnboardDevice.uni + MiscOnboardDeviceData.c + MiscOnboardDeviceFunction.c + MiscPortInternalConnectorDesignator.uni + MiscPortInternalConnectorDesignatorData.c + MiscPortInternalConnectorDesignatorFunction.c + MiscResetCapabilitiesData.c + MiscResetCapabilitiesFunction.c + MiscSystemLanguageString.uni + MiscSystemLanguageStringData.c + MiscSystemLanguageStringFunction.c + MiscSystemManufacturer.uni + MiscSystemManufacturerData.c + MiscSystemManufacturerFunction.c + MiscSystemOptionString.uni + MiscSystemOptionStringData.c + MiscSystemOptionStringFunction.c + MiscSystemSlotDesignation.uni + MiscSystemSlotDesignationData.c + MiscSystemSlotDesignationFunction.c + MiscSubclassDriver.h + MiscSubclassDriver.uni + MiscSubclassDriverDataTable.c + MiscSubclassDriverEntryPoint.c + CommonHeader.h + MiscOemType0x90Function.c + MiscOemType0x90Data.c + MiscOemType0x90.uni + MiscProcessorInformation.uni + MiscProcessorInformationData.c + MiscProcessorInformationFunction.c + MiscProcessorCache.uni + MiscProcessorCacheData.c + MiscProcessorCacheFunction.c + MiscPhysicalArray.uni + MiscPhysicalArrayData.c + MiscPhysicalArrayFunction.c + MiscMemoryDevice.uni + MiscMemoryDeviceData.c + MiscMemoryDeviceFunction.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + +[LibraryClasses] + HiiLib + DevicePathLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + DebugLib + BaseLib + MemoryAllocationLib + PcdLib + UefiLib + BiosIdLib + PrintLib + CpuIA32Lib + PchPlatformLib + I2cLib + NetLib + +[Guids] + gEfiProcessorSubClassGuid + gEfiCacheSubClassGuid + gEfiNormalSetupGuid + gEfiPlatformInfoGuid + gEfiVlv2VariableGuid + +[Protocols] + gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiDataHubProtocolGuid + gEfiMpServiceProtocolGuid + gMemInfoProtocolGuid + gEfiTdtOperationProtocolGuid + gDxePchPlatformPolicyProtocolGuid + gEfiSpiProtocolGuid + gEfiSimpleNetworkProtocolGuid + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareReleaseDateString + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang + gEfiVLVTokenSpaceGuid.PcdEmmcManufacturerId + gEfiVLVTokenSpaceGuid.PcdProductSerialNumber + +[Depex] + gEfiSmbiosProtocolGuid AND gMemInfoProtocolGuid AND gEfiMpServiceProtocolGuid AND gEfiSimpleNetworkProtocolGuid diff --git a/Vlv2TbltDevicePkg/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.c b/Vlv2TbltDevicePkg/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.c new file mode 100644 index 0000000000..c09c3d9ded --- /dev/null +++ b/Vlv2TbltDevicePkg/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.c @@ -0,0 +1,464 @@ +/** @file + SMM SwDispatch2 Protocol on SMM SwDispatch Protocol Thunk driver. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +typedef struct { + LIST_ENTRY Link; + EFI_HANDLE DispatchHandle; + UINTN SwSmiInputValue; + UINTN DispatchFunction; +} EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT; + +/** + Register a child SMI source dispatch function for the specified software SMI. + + This service registers a function (DispatchFunction) which will be called when the software + SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return, + DispatchHandle contains a unique handle which may be used later to unregister the function + using UnRegister(). + + @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when the specified software + SMI is generated. + @param[in, out] 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 which Software SMI input value the + dispatch function should be invoked for. + @param[out] 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 SW driver was unable to enable the SMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The SW SMI input value + is not within valid range. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this + child. + @retval EFI_OUT_OF_RESOURCES A unique software SMI value could not be assigned + for this dispatch. +**/ +EFI_STATUS +EFIAPI +SmmSwDispatch2Register ( + IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This, + IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction, + IN OUT EFI_SMM_SW_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a child SMI source dispatch function for the specified software SMI. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called in response to a software SMI. + + @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance. + @param[in] DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully unregistered. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. +**/ +EFI_STATUS +EFIAPI +SmmSwDispatch2UnRegister ( + IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +EFI_SMM_SW_DISPATCH2_PROTOCOL gSmmSwDispatch2 = { + SmmSwDispatch2Register, + SmmSwDispatch2UnRegister, + 0 // MaximumSwiValue +}; + +EFI_SMM_SW_DISPATCH_PROTOCOL *mSmmSwDispatch; +UINT8 mSmiTriggerRegister; +UINT8 mSmiDataRegister; + +EFI_SMM_CPU_PROTOCOL *mSmmCpuProtocol; +LIST_ENTRY mSmmSwDispatch2ThunkQueue = INITIALIZE_LIST_HEAD_VARIABLE (mSmmSwDispatch2ThunkQueue); + +/** + This function find SmmSwDispatch2Context by SwSmiInputValue. + + @param SwSmiInputValue The SwSmiInputValue to indentify the SmmSwDispatch2 context + + @return SmmSwDispatch2 context +**/ +EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT * +FindSmmSwDispatch2ContextBySwSmiInputValue ( + IN UINTN SwSmiInputValue + ) +{ + LIST_ENTRY *Link; + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext; + + for (Link = mSmmSwDispatch2ThunkQueue.ForwardLink; + Link != &mSmmSwDispatch2ThunkQueue; + Link = Link->ForwardLink) { + ThunkContext = BASE_CR ( + Link, + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT, + Link + ); + if (ThunkContext->SwSmiInputValue == SwSmiInputValue) { + return ThunkContext; + } + } + return NULL; +} + +/** + This function find SmmSwDispatch2Context by DispatchHandle. + + @param DispatchHandle The DispatchHandle to indentify the SmmSwDispatch2Thunk context + + @return SmmSwDispatch2Thunk context +**/ +EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT * +FindSmmSwDispatch2ContextByDispatchHandle ( + IN EFI_HANDLE DispatchHandle + ) +{ + LIST_ENTRY *Link; + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext; + + for (Link = mSmmSwDispatch2ThunkQueue.ForwardLink; + Link != &mSmmSwDispatch2ThunkQueue; + Link = Link->ForwardLink) { + ThunkContext = BASE_CR ( + Link, + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT, + Link + ); + if (ThunkContext->DispatchHandle == DispatchHandle) { + return ThunkContext; + } + } + return NULL; +} + +/** + Framework dispatch function for a Software SMI handler. + + @param DispatchHandle The handle of this dispatch function. + @param DispatchContext The pointer to the dispatch function's context. + The SwSmiInputValue field is filled in + by the software dispatch driver prior to + invoking this dispatch function. + The dispatch function will only be called + for input values for which it is registered. + + @return None + +**/ +VOID +EFIAPI +FrameworkDispatchFunction ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ) +{ + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext; + EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction; + EFI_SMM_SW_REGISTER_CONTEXT RegisterContext; + EFI_SMM_SW_CONTEXT SwContext; + UINTN Size; + UINTN Index; + EFI_SMM_SAVE_STATE_IO_INFO IoInfo; + EFI_STATUS Status; + + // + // Search context + // + ThunkContext = FindSmmSwDispatch2ContextBySwSmiInputValue (DispatchContext->SwSmiInputValue); + ASSERT (ThunkContext != NULL); + if (ThunkContext == NULL) { + return ; + } + + // + // Construct new context + // + RegisterContext.SwSmiInputValue = DispatchContext->SwSmiInputValue; + Size = sizeof(SwContext); + SwContext.CommandPort = IoRead8 (mSmiTriggerRegister); + SwContext.DataPort = IoRead8 (mSmiDataRegister); + + // + // Try to find which CPU trigger SWSMI + // + SwContext.SwSmiCpuIndex = 0; + for (Index = 0; Index < gSmst->NumberOfCpus; Index++) { + Status = mSmmCpuProtocol->ReadSaveState ( + mSmmCpuProtocol, + sizeof(IoInfo), + EFI_SMM_SAVE_STATE_REGISTER_IO, + Index, + &IoInfo + ); + if (EFI_ERROR (Status)) { + continue; + } + if (IoInfo.IoPort == mSmiTriggerRegister) { + // + // Great! Find it. + // + SwContext.SwSmiCpuIndex = Index; + break; + } + } + + // + // Dispatch + // + DispatchFunction = (EFI_SMM_HANDLER_ENTRY_POINT2)ThunkContext->DispatchFunction; + DispatchFunction ( + DispatchHandle, + &RegisterContext, + &SwContext, + &Size + ); + return ; +} + +/** + Register a child SMI source dispatch function for the specified software SMI. + + This service registers a function (DispatchFunction) which will be called when the software + SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return, + DispatchHandle contains a unique handle which may be used later to unregister the function + using UnRegister(). + + @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when the specified software + SMI is generated. + @param[in, out] 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 which Software SMI input value the + dispatch function should be invoked for. + @param[out] 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 SW driver was unable to enable the SMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The SW SMI input value + is not within valid range. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this + child. + @retval EFI_OUT_OF_RESOURCES A unique software SMI value could not be assigned + for this dispatch. +**/ +EFI_STATUS +EFIAPI +SmmSwDispatch2Register ( + IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This, + IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction, + IN OUT EFI_SMM_SW_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ) +{ + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext; + EFI_SMM_SW_DISPATCH_CONTEXT DispatchContext; + EFI_STATUS Status; + UINTN Index; + + if (RegisterContext->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 < gSmmSwDispatch2.MaximumSwiValue; Index++) { + DispatchContext.SwSmiInputValue = Index; + Status = mSmmSwDispatch->Register ( + mSmmSwDispatch, + FrameworkDispatchFunction, + &DispatchContext, + DispatchHandle + ); + if (!EFI_ERROR (Status)) { + RegisterContext->SwSmiInputValue = Index; + break; + } + } + if (RegisterContext->SwSmiInputValue == (UINTN)-1) { + return EFI_OUT_OF_RESOURCES; + } + } else { + DispatchContext.SwSmiInputValue = RegisterContext->SwSmiInputValue; + Status = mSmmSwDispatch->Register ( + mSmmSwDispatch, + FrameworkDispatchFunction, + &DispatchContext, + DispatchHandle + ); + } + if (!EFI_ERROR (Status)) { + // + // Register + // + Status = gSmst->SmmAllocatePool ( + EfiRuntimeServicesData, + sizeof(*ThunkContext), + (VOID **)&ThunkContext + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + mSmmSwDispatch->UnRegister (mSmmSwDispatch, *DispatchHandle); + return EFI_OUT_OF_RESOURCES; + } + + ThunkContext->SwSmiInputValue = RegisterContext->SwSmiInputValue; + ThunkContext->DispatchFunction = (UINTN)DispatchFunction; + ThunkContext->DispatchHandle = *DispatchHandle; + InsertTailList (&mSmmSwDispatch2ThunkQueue, &ThunkContext->Link); + } + + return Status; +} + +/** + Unregister a child SMI source dispatch function for the specified software SMI. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called in response to a software SMI. + + @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance. + @param[in] DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully unregistered. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. +**/ +EFI_STATUS +EFIAPI +SmmSwDispatch2UnRegister ( + IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ) +{ + EFI_SMM_SW_DISPATCH2_THUNK_CONTEXT *ThunkContext; + EFI_STATUS Status; + + Status = mSmmSwDispatch->UnRegister (mSmmSwDispatch, DispatchHandle); + if (!EFI_ERROR (Status)) { + // + // Unregister + // + ThunkContext = FindSmmSwDispatch2ContextByDispatchHandle (DispatchHandle); + ASSERT (ThunkContext != NULL); + if (ThunkContext != NULL) { + RemoveEntryList (&ThunkContext->Link); + gSmst->SmmFreePool (ThunkContext); + } + } + + return Status; +} + +/** + Entry Point for this thunk driver. + + @param[in] ImageHandle Image handle of this driver. + @param[in] SystemTable A Pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurred when executing this entry point. +**/ +EFI_STATUS +EFIAPI +SmmSwDispatch2ThunkMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_SMM_CONTROL_PROTOCOL *SmmControl; + EFI_SMM_CONTROL_REGISTER RegisterInfo; + + // + // Locate Framework SMM SwDispatch Protocol + // + Status = gBS->LocateProtocol ( + &gEfiSmmSwDispatchProtocolGuid, + NULL, + (VOID **)&mSmmSwDispatch + ); + ASSERT_EFI_ERROR (Status); + gSmmSwDispatch2.MaximumSwiValue = mSmmSwDispatch->MaximumSwiValue; + if (gSmmSwDispatch2.MaximumSwiValue == 0x0) { + DEBUG ((EFI_D_ERROR, "BUGBUG: MaximumSwiValue is 0, work-around to make it 0xFF\n")); + gSmmSwDispatch2.MaximumSwiValue = 0xFF; + } + + // + // Locate Framework SMM Control Protocol + // + Status = gBS->LocateProtocol ( + &gEfiSmmControlProtocolGuid, + NULL, + (VOID **)&SmmControl + ); + + ASSERT_EFI_ERROR (Status); + Status = SmmControl->GetRegisterInfo ( + SmmControl, + &RegisterInfo + ); + ASSERT_EFI_ERROR (Status); + mSmiTriggerRegister = RegisterInfo.SmiTriggerRegister; + mSmiDataRegister = RegisterInfo.SmiDataRegister; + + // + // Locate PI SMM CPU protocol + // + Status = gSmst->SmmLocateProtocol ( + &gEfiSmmCpuProtocolGuid, + NULL, + (VOID **)&mSmmCpuProtocol + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish PI SMM SwDispatch2 Protocol + // + ImageHandle = NULL; + Status = gSmst->SmmInstallProtocolInterface ( + &ImageHandle, + &gEfiSmmSwDispatch2ProtocolGuid, + EFI_NATIVE_INTERFACE, + &gSmmSwDispatch2 + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + diff --git a/Vlv2TbltDevicePkg/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf b/Vlv2TbltDevicePkg/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf new file mode 100644 index 0000000000..9663fc9bb7 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmmSwDispatch2OnSmmSwDispatchThunk/SmmSwDispatch2OnSmmSwDispatchThunk.inf @@ -0,0 +1,59 @@ +## @file +# Component description file for SMM SwDispatch2 Protocol on SMM SwDispatch Protocol Thunk driver. +# +# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmSwDispatch2OnSmmSwDispatchThunk + FILE_GUID = 1410C6AC-9F4B-495b-9C23-8A5AEB0165E9 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + ENTRY_POINT = SmmSwDispatch2ThunkMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmSwDispatch2OnSmmSwDispatchThunk.c + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + SmmServicesTableLib + BaseLib + IoLib + DebugLib + +[Protocols] + gEfiSmmControlProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiSmmSwDispatchProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiSmmCpuProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiSmmSwDispatch2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED + +[Depex] + gEfiSmmSwDispatchProtocolGuid AND + gEfiSmmControlProtocolGuid AND + gEfiSmmCpuProtocolGuid + diff --git a/Vlv2TbltDevicePkg/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.c b/Vlv2TbltDevicePkg/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.c new file mode 100644 index 0000000000..a48de262db --- /dev/null +++ b/Vlv2TbltDevicePkg/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.c @@ -0,0 +1,182 @@ +/** @file + A helper driver to save information to SMRAM after SMRR is enabled. + + This driver is for ECP platforms. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SMM_FROM_SMBASE_DRIVER 0x55 +#define SMM_FROM_CPU_DRIVER_SAVE_INFO 0x81 + +#define EFI_SMRAM_CPU_NVS_HEADER_GUID \ + { \ + 0x429501d9, 0xe447, 0x40f4, 0x86, 0x7b, 0x75, 0xc9, 0x3a, 0x1d, 0xb5, 0x4e \ + } + +UINT8 mSmiDataRegister; +BOOLEAN mLocked = FALSE; +EFI_GUID mSmramCpuNvsHeaderGuid = EFI_SMRAM_CPU_NVS_HEADER_GUID; + +/** + Dispatch function for a Software SMI handler. + + @param DispatchHandle The handle of this dispatch function. + @param DispatchContext The pointer to the dispatch function's context. + The SwSmiInputValue field is filled in + by the software dispatch driver prior to + invoking this dispatch function. + The dispatch function will only be called + for input values for which it is registered. + + @return None + +**/ +VOID +EFIAPI +SmramSaveInfoHandler ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ) +{ + EFI_STATUS Status; + UINT64 VarData[3]; + UINTN VarSize; + + ASSERT (DispatchContext != NULL); + ASSERT (DispatchContext->SwSmiInputValue == SMM_FROM_SMBASE_DRIVER); + + if (!mLocked && IoRead8 (mSmiDataRegister) == SMM_FROM_CPU_DRIVER_SAVE_INFO) { + VarSize = sizeof (VarData); + Status = gRT->GetVariable ( + L"SmramCpuNvs", + &mSmramCpuNvsHeaderGuid, + NULL, + &VarSize, + VarData + ); + if (!EFI_ERROR (Status) && VarSize == sizeof (VarData)) { + CopyMem ( + (VOID *)(UINTN)(VarData[0]), + (VOID *)(UINTN)(VarData[1]), + (UINTN)(VarData[2]) + ); + } + } +} + +/** + 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 function of this driver. + + @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 +SmramSaveInfoHandlerSmmMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_SMM_SW_DISPATCH_PROTOCOL *SmmSwDispatch; + EFI_SMM_SW_DISPATCH_CONTEXT SmmSwDispatchContext; + EFI_HANDLE DispatchHandle; + EFI_SMM_CONTROL_PROTOCOL *SmmControl; + EFI_SMM_CONTROL_REGISTER SmmControlRegister; + VOID *Registration; + + // + // Get SMI data register + // + Status = SystemTable->BootServices->LocateProtocol ( + &gEfiSmmControlProtocolGuid, + NULL, + (VOID **)&SmmControl + ); + ASSERT_EFI_ERROR (Status); + Status = SmmControl->GetRegisterInfo (SmmControl, &SmmControlRegister); + ASSERT_EFI_ERROR (Status); + mSmiDataRegister = SmmControlRegister.SmiDataRegister; + + // + // Register software SMI handler + // + + Status = SystemTable->BootServices->LocateProtocol ( + &gEfiSmmSwDispatchProtocolGuid, + NULL, + (VOID **)&SmmSwDispatch + ); + ASSERT_EFI_ERROR (Status); + + SmmSwDispatchContext.SwSmiInputValue = SMM_FROM_SMBASE_DRIVER; + Status = SmmSwDispatch->Register ( + SmmSwDispatch, + &SmramSaveInfoHandler, + &SmmSwDispatchContext, + &DispatchHandle + ); + ASSERT_EFI_ERROR (Status); + + // + // Register SMM Ready To Lock Protocol notification + // + Status = gSmst->SmmRegisterProtocolNotify ( + &gEfiSmmReadyToLockProtocolGuid, + SmmReadyToLockEventNotify, + &Registration + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + diff --git a/Vlv2TbltDevicePkg/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.inf b/Vlv2TbltDevicePkg/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.inf new file mode 100644 index 0000000000..82eec0152b --- /dev/null +++ b/Vlv2TbltDevicePkg/SmramSaveInfoHandlerSmm/SmramSaveInfoHandlerSmm.inf @@ -0,0 +1,59 @@ +## @file +# +# A helper driver to save information to SMRAM after SMRR is enabled. +# +# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmramSaveInfoHandlerSmm + FILE_GUID = 63296C52-01CF-4eea-A47C-782A14DA6894 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + + ENTRY_POINT = SmramSaveInfoHandlerSmmMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + SmramSaveInfoHandlerSmm.c + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + SmmServicesTableLib + BaseLib + BaseMemoryLib + IoLib + +[Protocols] + gEfiSmmSwDispatchProtocolGuid ## CONSUMED + gEfiSmmControlProtocolGuid ## CONSUMED + gEfiSmmReadyToLockProtocolGuid ## CONSUMED + +[Depex] + gEfiSmmSwDispatchProtocolGuid AND + gEfiSmmControlProtocolGuid + diff --git a/Vlv2TbltDevicePkg/Stitch/Gcc/NvStorageFtwSpare.bin b/Vlv2TbltDevicePkg/Stitch/Gcc/NvStorageFtwSpare.bin new file mode 100644 index 0000000000..7145947da4 --- /dev/null +++ b/Vlv2TbltDevicePkg/Stitch/Gcc/NvStorageFtwSpare.bin @@ -0,0 +1 @@ +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file diff --git a/Vlv2TbltDevicePkg/Stitch/Gcc/NvStorageFtwWorking.bin b/Vlv2TbltDevicePkg/Stitch/Gcc/NvStorageFtwWorking.bin new file mode 100644 index 0000000000000000000000000000000000000000..dcb92498b93463a07d6dd695cf30ae9320414671 GIT binary patch literal 8192 zcmeIuu?;{_6hP6R7(<~Jr73J+0f`|PLyL*bAV$#hh$$53R<}M?+0OkiHtW`f0uR>?&}A1LIf@PTeK(xHyKIkdam!ebMH78E;F~7$yq$#<#5jV&U?P^{ho8r zJ@-2ijpfM7zbhx+`{af3j~*N7*giZGvA7zrtAE@2%EY2rACE7|it=P_Y3k&It8Se; zbo{fPu@9bDI`q|nW0!wziW$}POD+ll0t5&U z_;&)WJfAwV$rJhbzP4xe@+%WpH=h3b%azM+p5ES{Pto3do{r|CEJ%S;E7$j-Onq7Y z|G4_}idTPFyL#Zmy$}EP?LY6Y=#Dq@;|edxD=R4i1PCk;fmWU~PiC(9k|55GoZor) zkKZ>QJ@w6%@$Ysl-5h;6$K9H<+P>({x$bbzX&Yy~#j#?hJ6N3w&;5{Fo2Nfe8cpr+e2rzY?^0=TbtAK>l_;0XMPiv+wWjF5*sG#X z$rk~Wb*1)t<@C$+U$V}2@`kFFwy6#m)!HvbE59p`=J_+&U}|v6aoYY z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs r0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7e?{~~Y)M6B04 literal 0 HcmV?d00001 diff --git a/Vlv2TbltDevicePkg/Stitch/IFWIHeader/IFWI_HEADER.bin b/Vlv2TbltDevicePkg/Stitch/IFWIHeader/IFWI_HEADER.bin new file mode 100644 index 0000000000000000000000000000000000000000..5c26f1ed01e86d78b04087b037932a86b08a53bc GIT binary patch literal 4096 zcmezW9~DF`{lL%6z{14FB*3k}pva)gz`%g4LWMy9C;|Z>aWISZKRYACe-;q?zdWjX z5D!%Z*|dRYLwo`xSy+LDfCL}I0!K!u;9+(KhQrJZ4DLWa2oJn#M_n))0;3@?8Umvs zFd71*Aut*OqaiRF0;3@?8Un +@REM +@REM This program and the accompanying materials are licensed and made available under +@REM the terms and conditions of the BSD License that accompanies this distribution. +@REM The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php. +@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 + +@echo off +SetLocal EnableDelayedExpansion EnableExtensions + +:: Set script defaults +set exitCode=0 +set BackupRom=1 +set UpdateVBios=1 +set Stitch_Config=Stitch_Config.txt +copy /y nul Stitching.log >nul + +:: Set default Suffix as: YYYY_MM_DD_HHMM +set hour=%time: =0% +reg copy "HKCU\Control Panel\International" "HKCU\Control Panel\International_Temp" /f >nul +reg add "HKCU\Control Panel\International" /v sShortDate /d "yyyy_MM_dd" /f >nul +for /f "tokens=1" %%i in ("%date%") do set today=%%i +reg copy "HKCU\Control Panel\International_Temp" "HKCU\Control Panel\International" /f >nul +reg delete "HKCU\Control Panel\International_Temp" /f >nul +set IFWI_Suffix=%today%_%hour:~0,2%%time:~3,2% + +:: Process input arguments +if "%~1"=="?" goto Usage +if "%~1"=="/?" goto Usage +if /i "%~1"=="Help" goto Usage + +:OptLoop +if /i "%~1"=="/nV" ( + set UpdateVBios=0 + shift + goto OptLoop +) +if /i "%~1"=="/nB" ( + set BackupRom=0 + shift + goto OptLoop +) +if /i "%~1"=="/B" ( + if "%~2"=="" goto Usage + if not exist %~2 echo BIOS not found. & goto Usage + set BIOS_Names=%~2 + set BIOS_File_Name=%~n2 + shift & shift + goto OptLoop +) +if /i "%~1"=="/C" ( + if "%~2"=="" goto Usage + if not exist %~2 echo ConfigFile not found. & goto Usage + set Stitch_Config=%~2 + shift & shift + goto OptLoop +) +if /i "%~1"=="/S" ( + if "%~2"=="" goto Usage + set IFWI_Suffix=%~2 + shift & shift + goto OptLoop +) + +if "%BIOS_File_Name:~0,4%"=="MNW2" ( + set Stitch_Config= MNW2_Stitch_Config.txt +) +if "%BIOS_File_Name:~3,4%"=="MNW2" ( + set Stitch_Config= MNW2_Stitch_Config.txt +) + +:: if no rom specified by user, search in ./ for ROM files +if "%BIOS_Names%"=="" ( + set "BIOS_Names= " + for /f "tokens=*" %%i in ('dir /b *.rom') do set BIOS_Names=!BIOS_Names! %%i + if "!BIOS_Names!"==" " ( + echo NO .ROM files found !!! + goto Usage + ) +) + +:: Parse the Stitch_Config File +if not exist %Stitch_Config% ( + echo Stitch Configuration File %Stitch_Config% not found. + goto ScriptFail +) +for /f "delims== tokens=1,2" %%i in (%Stitch_Config%) do ( + if /i "%%i"=="HEADER" set IFWI_HEADER=%%j + if /i "%%i"=="SEC_VERSION" set SEC_VERSION=%%j + if /i "%%i"=="Source" ( + if /i "%%j"=="ALPHA" set Source_Prefix=A_ + if /i "%%j"=="BF" set Source_Prefix=BF_ + if /i "%%j"=="BE" set Source_Prefix=BE_ + if /i "%%j"=="PV" set Source_Prefix=PV_ + if /i "%%j"=="PR1" set Source_Prefix=PR1_ + ) +) + + +:: ********************************************************************** +:: The Main Stitching Loop +:: ********************************************************************** +echo %date% %time% >>Stitching.log 2>&1 +echo %date% %time% +echo. +for %%i in (%BIOS_Names%) do ( + + REM ----- Do NOT use :: for comments Inside of code blocks() ------- + set BIOS_Rom=%%i + set BIOS_Name=%%~ni + set BIOS_Version=!BIOS_Name:~-7,7! + + REM extract PlatformType from BIOS filename + set Platform_Type=!BIOS_Name:~0,4! + + REM Special treat for BayLake FFD8 + set Temp_Name=!BIOS_Name:~0,7! + + + REM Capitalize and validate the Platform_Type + if /i "!Platform_Type!"=="MNW2" ( + set Platform_Type=MNW2 + ) else ( + echo Error - Unsupported PlatformType: !Platform_Type! + goto Usage + ) + + + REM search BIOS_Name for Arch substring: either IA32 or X64 + if not "!BIOS_Name!"=="!BIOS_Name:_IA32_=!" ( + set Arch=IA32 + ) else if not "!BIOS_Name!"=="!BIOS_Name:_X64_=!" ( + set Arch=X64 + ) else ( + echo Error: Could not determine Architecture for !BIOS_Rom! + goto Usage + ) + set IFWI_Prefix=!Platform_Type!_IFWI_%Source_Prefix%!Arch!_!!BIOS_Version! + + REM search BIOS_Name for Build_Target substring: either R or D + if not "!BIOS_Name!"=="!BIOS_Name:_R_=!" ( + set Build_Target=Release + set IFWI_Prefix=!IFWI_Prefix!_R + ) else if not "!BIOS_Name!"=="!BIOS_Name:_D_=!" ( + set Build_Target=Debug + set IFWI_Prefix=!IFWI_Prefix!_D + ) else ( + echo Error: Could not determine Build Target for !BIOS_Rom! + goto Usage + ) + + REM Create a BIOS backup before Stitching + if %BackupRom% EQU 1 ( + echo Creating backup of original BIOS rom. + copy /y !BIOS_Rom! !BIOS_Rom!.orig >nul + ) + + echo. >>Stitching.log + echo ********** Stitching !BIOS_Rom! ********** >>Stitching.log + echo. >>Stitching.log + echo. + echo Stitching IFWI for !BIOS_Rom! ... + echo --------------------------------------------------------------------------- + echo IFWI Header: !IFWI_HEADER!.bin, SEC version: !SEC_VERSION!, + echo BIOS Version: !BIOS_Version! + + echo Platform Type: !Platform_Type!, IFWI Prefix: %BIOS_ID% + echo --------------------------------------------------------------------------- + + echo ----------------------------- + echo. + echo Generating IFWI... %BIOS_ID%.bin + echo. + copy /b/y IFWIHeader\!IFWI_HEADER!.bin + ..\..\Vlv2MiscBinariesPkg\SEC\!SEC_VERSION!\VLV_SEC_REGION.bin + IFWIHeader\Vacant.bin + !BIOS_Rom! %BIOS_ID%.bin + echo. + echo =========================================================================== +) +@echo off + +::********************************************************************** +:: end of main loop +::********************************************************************** + +echo. +echo -- All specified ROM files Stitched. -- +echo. +goto Exit + +:Usage +echo. +echo ************************************************************************************************** +echo This Script is used to Stitch together BIOS, GOP Driver, Microcode Patch and TXE FW +echo into a single Integrated Firmware Image (IFWI). +echo. +echo Usage: IFWIStitch.bat [flags] [/B BIOS.ROM] [/C Stitch_Config] [/S IFWI_Suffix] +echo. +echo This script has NO Required arguments, so that the user can just double click from the GUI. +echo However, this requires that the BIOS.ROM file name is formatted correctly. +echo. +echo /nG Do NOT update the GOP driver. (applies to all ROM files for this run) +echo /nV Do NOT update the VBIOS. (applies to all ROM files for this run) +echo /nM Do NOT update the Microcode. (applies to all ROM files for this run) +echo /nB Do NOT backup BIOS.ROMs. (Default will backup to BIOS.ROM.Orig) +echo. +echo BIOS.ROM: A single BIOS ROM file to use for stitching +echo (DEFAULT: ALL .ROM files inside the current directory) +echo Stitch_Config: Text file containing version info of each FW component +echo (DEFAULT: Stitch_Config.txt) +echo IFWI_Suffix: Suffix to append to the end of the IFWI filename +echo (DEFAULT: YYYY_MM_DD_HHMM) +echo. +echo Examples: +echo IFIWStitch.bat : Stitch all ROMs with defaults +echo IFIWStitch.bat /B C:/MyRoms/testBIOS.rom : Stitch single ROM with defaults +echo IFIWStitch.bat /B ../testBIOS.rom /S test123 : Stitch single ROM and add custom suffix +echo IFIWStitch.bat /nM /nB /B testBIOS.rom /S test456 : Stitch single ROM, keep uCode from .rom, +echo don't create backup, and add custom suffix. +echo **************************************************************************************************** +pause +exit /b 1 + +:ScriptFail +set exitCode=1 + +:Exit +echo -- See Stitching.log for more info. -- +echo. +echo %date% %time% +echo. +if "%Platform_Type%"=="MNW2" ( + echo . +) else ( + echo only support MNW2 for this project! +pause +) +exit /b %exitCode% +EndLocal diff --git a/Vlv2TbltDevicePkg/Stitch/MNW2_Stitch_Config.txt b/Vlv2TbltDevicePkg/Stitch/MNW2_Stitch_Config.txt new file mode 100644 index 0000000000..5a0a2b4911 --- /dev/null +++ b/Vlv2TbltDevicePkg/Stitch/MNW2_Stitch_Config.txt @@ -0,0 +1,16 @@ +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# + +HEADER=IFWI_HEADER +SEC_VERSION=1.0.2.1060v5 + diff --git a/Vlv2TbltDevicePkg/UiApp/FrontPage.c b/Vlv2TbltDevicePkg/UiApp/FrontPage.c new file mode 100644 index 0000000000..e18a9fcace --- /dev/null +++ b/Vlv2TbltDevicePkg/UiApp/FrontPage.c @@ -0,0 +1,38 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +**/ + +/** + The user Entry Point for Application. The user code starts with this function + as the real entry point for the image goes into a library that calls 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 +InitializeUserInterface ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/UiApp/UiApp.inf b/Vlv2TbltDevicePkg/UiApp/UiApp.inf new file mode 100644 index 0000000000..08b558489e --- /dev/null +++ b/Vlv2TbltDevicePkg/UiApp/UiApp.inf @@ -0,0 +1,37 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UiApp + FILE_GUID = 462CAA21-7614-4503-836E-8AB6F4662331 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeUserInterface + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + FrontPage.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint diff --git a/Vlv2TbltDevicePkg/VlvPlatformInitDxe/IgdOpRegion.c b/Vlv2TbltDevicePkg/VlvPlatformInitDxe/IgdOpRegion.c new file mode 100644 index 0000000000..2200e6c751 --- /dev/null +++ b/Vlv2TbltDevicePkg/VlvPlatformInitDxe/IgdOpRegion.c @@ -0,0 +1,938 @@ + +/*++ + +Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + IgdOpRegion.c + +Abstract: + + This is part of the implementation of an Intel Graphics drivers OpRegion / + Software SCI interface between system BIOS, ASL code, and Graphics drivers. + The code in this file will load the driver and initialize the interface + + Supporting Specifiction: OpRegion / Software SCI SPEC 0.70 + + Acronyms: + IGD: Internal Graphics Device + NVS: ACPI Non Volatile Storage + OpRegion: ACPI Operational Region + VBT: Video BIOS Table (OEM customizable data) + +--*/ + +// +// Include files +// + + +#include "IgdOpRegion.h" +#include "VlvPlatformInit.h" +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + + +UINT8 gSVER[12] = "Intel"; + +extern DXE_VLV_PLATFORM_POLICY_PROTOCOL *DxePlatformSaPolicy; + +// +// Global variables +// + +IGD_OPREGION_PROTOCOL mIgdOpRegion; +EFI_GUID mMiscSubClass = EFI_MISC_SUBCLASS_GUID; +EFI_EVENT mConOutEvent; +EFI_EVENT mSetGOPverEvent; +VOID *mConOutReg; + +#define DEFAULT_FORM_BUFFER_SIZE 0xFFFF +#ifndef ECP_FLAG +#if 0 +/** + + Get the HII protocol interface + + @param Hii HII protocol interface + + @retval Status code + +**/ +static +EFI_STATUS +GetHiiInterface ( + OUT EFI_HII_PROTOCOL **Hii + ) +{ + EFI_STATUS Status; + + // + // There should only be one HII protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiProtocolGuid, + NULL, + (VOID **) Hii + ); + + return Status;; +} +#endif +#endif + +/** + + Get VBT data. + + @param[in] VbtFileBuffer Pointer to VBT data buffer. + + @retval EFI_SUCCESS VBT data was returned. + @retval EFI_NOT_FOUND VBT data not found. + @exception EFI_UNSUPPORTED Invalid signature in VBT data. + +**/ +EFI_STATUS +GetIntegratedIntelVbtPtr ( + OUT VBIOS_VBT_STRUCTURE **VbtFileBuffer + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS VbtAddress = 0; + UINT32 VbtSize = 0; + UINTN FvProtocolCount; + EFI_HANDLE *FvHandles; + EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; + UINTN Index; + UINT32 AuthenticationStatus; + + UINT8 *Buffer; + UINTN VbtBufferSize = 0; + + Buffer = 0; + FvHandles = NULL; + *VbtFileBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeProtocolGuid, + NULL, + &FvProtocolCount, + &FvHandles + ); + + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < FvProtocolCount; Index++) { + Status = gBS->HandleProtocol ( + FvHandles[Index], + &gEfiFirmwareVolumeProtocolGuid, + (VOID **) &Fv + ); + VbtBufferSize = 0; + Status = Fv->ReadSection ( + Fv, + &gBmpImageGuid, + EFI_SECTION_RAW, + 0, + (void **)&Buffer, + &VbtBufferSize, + &AuthenticationStatus + ); + + if (!EFI_ERROR (Status)) { + VbtAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + VbtSize = (UINT32)VbtBufferSize; + Status = EFI_SUCCESS; + break; + } + } + } else { + Status = EFI_NOT_FOUND; + } + + if (FvHandles != NULL) { + FreePool(FvHandles); + FvHandles = NULL; + } + + + // + // Check VBT signature + // + *VbtFileBuffer = (VBIOS_VBT_STRUCTURE *) (UINTN) VbtAddress; + if (*VbtFileBuffer != NULL) { + if ((*((UINT32 *) ((*VbtFileBuffer)->HeaderSignature))) != VBT_SIGNATURE) { + if (*VbtFileBuffer != NULL) { + *VbtFileBuffer = NULL; + } + return EFI_UNSUPPORTED; + } + // + // Check VBT size + // + if ((*VbtFileBuffer)->HeaderVbtSize > VbtBufferSize) { + (*VbtFileBuffer)->HeaderVbtSize = (UINT16) VbtBufferSize; + } + } + + return EFI_SUCCESS; +} + +// +// Function implementations. +// +/** + + Get a pointer to an uncompressed image of the Intel video BIOS. + + Note: This function would only be called if the video BIOS at 0xC000 is + missing or not an Intel video BIOS. It may not be an Intel video BIOS + if the Intel graphic contoller is considered a secondary adapter. + + + @param VBiosROMImage Pointer to an uncompressed Intel video BIOS. This pointer must + be set to NULL if an uncompressed image of the Intel Video BIOS + is not obtainable. + + + @retval EFI_SUCCESS VBiosPtr is updated. + +**/ +EFI_STATUS +GetIntegratedIntelVBiosPtr ( + INTEL_VBIOS_OPTION_ROM_HEADER **VBiosImage + ) +{ + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + INTEL_VBIOS_PCIR_STRUCTURE *PcirBlockPtr; + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + INTEL_VBIOS_OPTION_ROM_HEADER *VBiosRomImage; + + // + // Set as if an umcompressed Intel video BIOS image was not obtainable. + // + VBiosRomImage = NULL; + *VBiosImage = NULL; + + // + // Get all PCI IO protocols + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + ASSERT_EFI_ERROR (Status); + + // + // Find the video BIOS by checking each PCI IO handle for an Intel video + // BIOS OPROM. + // + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (void **)&PciIo + ); + ASSERT_EFI_ERROR (Status); + + VBiosRomImage = PciIo->RomImage; + + // + // If this PCI device doesn't have a ROM image, skip to the next device. + // + if (!VBiosRomImage) { + continue; + } + + // + // Get pointer to PCIR structure + // + PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *)((UINT8 *) VBiosRomImage + VBiosRomImage->PcirOffset); + + // + // Check if we have an Intel video BIOS OPROM. + // + if ((VBiosRomImage->Signature == OPTION_ROM_SIGNATURE) && + (PcirBlockPtr->VendorId == IGD_VID) && + (PcirBlockPtr->ClassCode[0] == 0x00) && + (PcirBlockPtr->ClassCode[1] == 0x00) && + (PcirBlockPtr->ClassCode[2] == 0x03) + ) { + // + // Found Intel video BIOS. + // + *VBiosImage = VBiosRomImage; + return EFI_SUCCESS; + } + } + + // + // No Intel video BIOS found. + // + + // + // Free any allocated buffers + // + return EFI_UNSUPPORTED; +} + +EFI_STATUS +SearchChildHandle( + EFI_HANDLE Father, + EFI_HANDLE *Child + ) +{ + EFI_STATUS Status; + UINTN HandleIndex; + EFI_GUID **ProtocolGuidArray = NULL; + UINTN ArrayCount; + UINTN ProtocolIndex; + UINTN OpenInfoCount; + UINTN OpenInfoIndex; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo = NULL; + UINTN mHandleCount; + EFI_HANDLE *mHandleBuffer= NULL; + + // + // Retrieve the list of all handles from the handle database + // + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &mHandleCount, + &mHandleBuffer + ); + + for (HandleIndex = 0; HandleIndex < mHandleCount; HandleIndex++) { + // + // Retrieve the list of all the protocols on each handle + // + Status = gBS->ProtocolsPerHandle ( + mHandleBuffer[HandleIndex], + &ProtocolGuidArray, + &ArrayCount + ); + if (!EFI_ERROR (Status)) { + for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) { + Status = gBS->OpenProtocolInformation ( + mHandleBuffer[HandleIndex], + ProtocolGuidArray[ProtocolIndex], + &OpenInfo, + &OpenInfoCount + ); + if (!EFI_ERROR (Status)) { + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { + if(OpenInfo[OpenInfoIndex].AgentHandle == Father) { + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) { + *Child = mHandleBuffer[HandleIndex]; + Status = EFI_SUCCESS; + goto TryReturn; + } + } + } + Status = EFI_NOT_FOUND; + } + } + if(OpenInfo != NULL) { + FreePool(OpenInfo); + OpenInfo = NULL; + } + } + FreePool (ProtocolGuidArray); + ProtocolGuidArray = NULL; + } +TryReturn: + if(OpenInfo != NULL) { + FreePool (OpenInfo); + OpenInfo = NULL; + } + if(ProtocolGuidArray != NULL) { + FreePool(ProtocolGuidArray); + ProtocolGuidArray = NULL; + } + if(mHandleBuffer != NULL) { + FreePool (mHandleBuffer); + mHandleBuffer = NULL; + } + return Status; +} + +EFI_STATUS +JudgeHandleIsPCIDevice( + EFI_HANDLE Handle, + UINT8 Device, + UINT8 Funs + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH *DPath; + EFI_DEVICE_PATH *DevicePath; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DPath + ); + if(!EFI_ERROR(Status)) { + DevicePath = DPath; + while(!IsDevicePathEnd(DPath)) { + if((DPath->Type == HARDWARE_DEVICE_PATH) && (DPath->SubType == HW_PCI_DP)) { + PCI_DEVICE_PATH *PCIPath; + + PCIPath = (PCI_DEVICE_PATH*) DPath; + DPath = NextDevicePathNode(DPath); + if(IsDevicePathEnd(DPath) && (PCIPath->Device == Device) && (PCIPath->Function == Funs)) { + return EFI_SUCCESS; + } + } else { + DPath = NextDevicePathNode(DPath); + } + } + } + return EFI_UNSUPPORTED; +} + +EFI_STATUS +GetDriverName( + EFI_HANDLE Handle, + CHAR16 *GopVersion + ) +{ + EFI_DRIVER_BINDING_PROTOCOL *BindHandle = NULL; + EFI_STATUS Status; + UINT32 Version; + UINT16 *Ptr; + + Status = gBS->OpenProtocol( + Handle, + &gEfiDriverBindingProtocolGuid, + (VOID**)&BindHandle, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) { + return EFI_NOT_FOUND; + } + + Version = BindHandle->Version; + Ptr = (UINT16*)&Version; + UnicodeSPrint(GopVersion, 40, L"7.0.%04d", *(Ptr)); + return EFI_SUCCESS; +} + +EFI_STATUS +GetGOPDriverVersion( + CHAR16 *GopVersion + ) +{ + UINTN HandleCount; + EFI_HANDLE *Handles= NULL; + UINTN Index; + EFI_STATUS Status; + EFI_HANDLE Child = 0; + + Status = gBS->LocateHandleBuffer( + ByProtocol, + &gEfiDriverBindingProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + for (Index = 0; Index < HandleCount ; Index++) { + Status = SearchChildHandle(Handles[Index], &Child); + if(!EFI_ERROR(Status)) { + Status = JudgeHandleIsPCIDevice(Child, 0x02, 0x00); + if(!EFI_ERROR(Status)) { + return GetDriverName(Handles[Index], GopVersion); + } + } + } + return EFI_UNSUPPORTED; +} + + +/** + Get Intel GOP driver version and copy it into IGD OpRegion GVER. This version + is picked up by IGD driver and displayed in CUI. + + @param Event A pointer to the Event that triggered the callback. + @param Context A pointer to private data registered with the callback function. + + @retval EFI_SUCCESS Video BIOS VBT information returned. + @retval EFI_UNSUPPORTED Could not find VBT information (*VBiosVbtPtr = NULL). + +**/ +EFI_STATUS +EFIAPI +SetGOPVersionCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + CHAR16 GopVersion[16] = {0}; + EFI_STATUS Status; + + Status = GetGOPDriverVersion(GopVersion); + if(!EFI_ERROR(Status)) { + StrCpy((CHAR16*)&(mIgdOpRegion.OpRegion->Header.GOPV[0]), GopVersion); + return Status; + } + return EFI_UNSUPPORTED; +} + +/** + Get Intel video BIOS VBT information (i.e. Pointer to VBT and VBT size). + The VBT (Video BIOS Table) is a block of customizable data that is built + within the video BIOS and edited by customers. + + @param Event A pointer to the Event that triggered the callback. + @param Context A pointer to private data registered with the callback function. + + @retval EFI_SUCCESS Video BIOS VBT information returned. + @retval EFI_UNSUPPORTED Could not find VBT information (*VBiosVbtPtr = NULL). + +**/ +EFI_STATUS +GetVBiosVbtCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + INTEL_VBIOS_PCIR_STRUCTURE *PcirBlockPtr; + UINT16 PciVenderId; + UINT16 PciDeviceId; + INTEL_VBIOS_OPTION_ROM_HEADER *VBiosPtr; + VBIOS_VBT_STRUCTURE *VBiosVbtPtr; + VBIOS_VBT_STRUCTURE *VbtFileBuffer = NULL; + + VBiosPtr = (INTEL_VBIOS_OPTION_ROM_HEADER *)(UINTN)(VBIOS_LOCATION_PRIMARY); + PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *)((UINT8 *)VBiosPtr + VBiosPtr->PcirOffset); + PciVenderId = PcirBlockPtr->VendorId; + PciDeviceId = PcirBlockPtr->DeviceId; + + // + // If the video BIOS is not at 0xC0000 or it is not an Intel video BIOS get + // the integrated Intel video BIOS (must be uncompressed). + // + if ((VBiosPtr->Signature != OPTION_ROM_SIGNATURE) || (PciVenderId != IGD_VID) || (PciDeviceId != IGD_DID_VLV)) { + GetIntegratedIntelVBiosPtr (&VBiosPtr); + + if(VBiosPtr) { + // + // Video BIOS found. + // + PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *)((UINT8 *)VBiosPtr + VBiosPtr->PcirOffset); + PciVenderId = PcirBlockPtr->VendorId; + if( (VBiosPtr->Signature != OPTION_ROM_SIGNATURE) || (PciVenderId != IGD_VID)) { + // + // Intel video BIOS not found. + // + VBiosVbtPtr = NULL; + return EFI_UNSUPPORTED; + } + } else { + // + // No Video BIOS found, try to get VBT from FV. + // + GetIntegratedIntelVbtPtr (&VbtFileBuffer); + if (VbtFileBuffer != NULL) { + // + // Video BIOS not found, use VBT from FV + // + DEBUG ((EFI_D_ERROR, "VBT data found\n")); + (gBS->CopyMem) ( + mIgdOpRegion.OpRegion->VBT.GVD1, + VbtFileBuffer, + VbtFileBuffer->HeaderVbtSize + ); + FreePool (VbtFileBuffer); + return EFI_SUCCESS; + } + } + if ((VBiosPtr == NULL) ) { + // + // Intel video BIOS not found. + // + VBiosVbtPtr = NULL; + return EFI_UNSUPPORTED; + } + } + + DEBUG ((EFI_D_ERROR, "VBIOS found at 0x%X\n", VBiosPtr)); + VBiosVbtPtr = (VBIOS_VBT_STRUCTURE *) ((UINT8 *) VBiosPtr + VBiosPtr->VbtOffset); + + if ((*((UINT32 *) (VBiosVbtPtr->HeaderSignature))) != VBT_SIGNATURE) { + return EFI_UNSUPPORTED; + } + + // + // Initialize Video BIOS version with its build number. + // + mIgdOpRegion.OpRegion->Header.VVER[0] = VBiosVbtPtr->CoreBlockBiosBuild[0]; + mIgdOpRegion.OpRegion->Header.VVER[1] = VBiosVbtPtr->CoreBlockBiosBuild[1]; + mIgdOpRegion.OpRegion->Header.VVER[2] = VBiosVbtPtr->CoreBlockBiosBuild[2]; + mIgdOpRegion.OpRegion->Header.VVER[3] = VBiosVbtPtr->CoreBlockBiosBuild[3]; + (gBS->CopyMem) ( + mIgdOpRegion.OpRegion->VBT.GVD1, + VBiosVbtPtr, + VBiosVbtPtr->HeaderVbtSize + ); + + // + // Return final status + // + return EFI_SUCCESS; +} + +/** + Graphics OpRegion / Software SCI driver installation function. + + @param ImageHandle Handle for this drivers loaded image protocol. + @param SystemTable EFI system table. + + @retval EFI_SUCCESS The driver installed without error. + @retval EFI_ABORTED The driver encountered an error and could not complete + installation of the ACPI tables. + +**/ +EFI_STATUS +IgdOpRegionInit ( + void + ) +{ + EFI_HANDLE Handle; + EFI_STATUS Status; + EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea; + UINT32 DwordData; + EFI_CPU_IO_PROTOCOL *CpuIo; + UINT16 Data16; + UINT16 AcpiBase; + VOID *gConOutNotifyReg; + + + // + // Locate the Global NVS Protocol. + // + Status = gBS->LocateProtocol ( + &gEfiGlobalNvsAreaProtocolGuid, + NULL, + (void **)&GlobalNvsArea + ); + ASSERT_EFI_ERROR (Status); + + // + // Allocate an ACPI NVS memory buffer as the IGD OpRegion, zero initialize + // the first 1K, and set the IGD OpRegion pointer in the Global NVS + // area structure. + // + Status = (gBS->AllocatePool) ( + EfiACPIMemoryNVS, + sizeof (IGD_OPREGION_STRUC), + (void **)&mIgdOpRegion.OpRegion + ); + ASSERT_EFI_ERROR (Status); + (gBS->SetMem) ( + mIgdOpRegion.OpRegion, + sizeof (IGD_OPREGION_STRUC), + 0 + ); + GlobalNvsArea->Area->IgdOpRegionAddress = (UINT32)(UINTN)(mIgdOpRegion.OpRegion); + + // + // If IGD is disabled return + // + if (IgdMmPci32 (0) == 0xFFFFFFFF) { + return EFI_SUCCESS; + } + + // + // Initialize OpRegion Header + // + + (gBS->CopyMem) ( + mIgdOpRegion.OpRegion->Header.SIGN, + HEADER_SIGNATURE, + sizeof(HEADER_SIGNATURE) + ); + + + // + // Set OpRegion Size in KBs + // + mIgdOpRegion.OpRegion->Header.SIZE = HEADER_SIZE/1024; + + // + // FIXME: Need to check Header OVER Field and the supported version. + // + mIgdOpRegion.OpRegion->Header.OVER = (UINT32) (LShiftU64 (HEADER_OPREGION_VER, 16) + LShiftU64 (HEADER_OPREGION_REV, 8)); +#ifdef ECP_FLAG + CopyMem(mIgdOpRegion.OpRegion->Header.SVER, gSVER, sizeof(gSVER)); +#else + gBS->CopyMem( + mIgdOpRegion.OpRegion->Header.SVER, + gSVER, + sizeof(gSVER) + ); +#endif + DEBUG ((EFI_D_ERROR, "System BIOS ID is %a\n", mIgdOpRegion.OpRegion->Header.SVER)); + + + mIgdOpRegion.OpRegion->Header.MBOX = HEADER_MBOX_SUPPORT; + + if( 1 == DxePlatformSaPolicy->IdleReserve) { + mIgdOpRegion.OpRegion->Header.PCON = (mIgdOpRegion.OpRegion->Header.PCON & 0xFFFC) | BIT1; + } else { + mIgdOpRegion.OpRegion->Header.PCON = (mIgdOpRegion.OpRegion->Header.PCON & 0xFFFC) | (BIT1 | BIT0); + } + + // + //For graphics driver to identify if LPE Audio/HD Audio is enabled on the platform + // + mIgdOpRegion.OpRegion->Header.PCON &= AUDIO_TYPE_SUPPORT_MASK; + mIgdOpRegion.OpRegion->Header.PCON &= AUDIO_TYPE_FIELD_MASK; + if ( 1 == DxePlatformSaPolicy->AudioTypeSupport ) { + mIgdOpRegion.OpRegion->Header.PCON = HD_AUDIO_SUPPORT; + mIgdOpRegion.OpRegion->Header.PCON |= AUDIO_TYPE_FIELD_VALID; + } + + // + // Initialize OpRegion Mailbox 1 (Public ACPI Methods). + // + // The initial setting of mailbox 1 fields is implementation specific. + // Adjust them as needed many even coming from user setting in setup. + // + //Workaround to solve LVDS is off after entering OS in desktop platform + // + mIgdOpRegion.OpRegion->MBox1.CLID = DxePlatformSaPolicy->IgdPanelFeatures.LidStatus; + + // + // Initialize OpRegion Mailbox 3 (ASLE Interrupt and Power Conservation). + // + // The initial setting of mailbox 3 fields is implementation specific. + // Adjust them as needed many even coming from user setting in setup. + // + + // + // Do not initialize TCHE. This field is written by the graphics driver only. + // + + // + // The ALSI field is generally initialized by ASL code by reading the embedded controller. + // + + mIgdOpRegion.OpRegion->MBox3.BCLP = BACKLIGHT_BRIGHTNESS; + + mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_STRETCH); + if ( DxePlatformSaPolicy->IgdPanelFeatures.PFITStatus == 2) { + // + // Center + // + mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_CENTER); + } else if (DxePlatformSaPolicy->IgdPanelFeatures.PFITStatus == 1) { + // + // Stretch + // + mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_STRETCH); + } else { + // + // Auto + // + mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_SETUP_AUTO); + } + + // + // Set Initial current Brightness + // + mIgdOpRegion.OpRegion->MBox3.CBLV = (INIT_BRIGHT_LEVEL | FIELD_VALID_BIT); + + // + // Create a static Backlight Brightness Level Duty cycle Mapping Table + // Possible 20 entries (example used 10), each 16 bits as follows: + // [15] = Field Valid bit, [14:08] = Level in Percentage (0-64h), [07:00] = Desired duty cycle (0 - FFh). + // + // % Brightness + mIgdOpRegion.OpRegion->MBox3.BCLM[0] = ( ( 0 << 8 ) + ( 0xFF - 0xFC ) + WORD_FIELD_VALID_BIT); + mIgdOpRegion.OpRegion->MBox3.BCLM[1] = ( ( 1 << 8 ) + ( 0xFF - 0xFC ) + WORD_FIELD_VALID_BIT); + mIgdOpRegion.OpRegion->MBox3.BCLM[2] = ( ( 10 << 8 ) + ( 0xFF - 0xE5 ) + WORD_FIELD_VALID_BIT); + mIgdOpRegion.OpRegion->MBox3.BCLM[3] = ( ( 19 << 8 ) + ( 0xFF - 0xCE ) + WORD_FIELD_VALID_BIT); + mIgdOpRegion.OpRegion->MBox3.BCLM[4] = ( ( 28 << 8 ) + ( 0xFF - 0xB7 ) + WORD_FIELD_VALID_BIT); + mIgdOpRegion.OpRegion->MBox3.BCLM[5] = ( ( 37 << 8 ) + ( 0xFF - 0xA0 ) + WORD_FIELD_VALID_BIT); + mIgdOpRegion.OpRegion->MBox3.BCLM[6] = ( ( 46 << 8 ) + ( 0xFF - 0x89 ) + WORD_FIELD_VALID_BIT); + mIgdOpRegion.OpRegion->MBox3.BCLM[7] = ( ( 55 << 8 ) + ( 0xFF - 0x72 ) + WORD_FIELD_VALID_BIT); + mIgdOpRegion.OpRegion->MBox3.BCLM[8] = ( ( 64 << 8 ) + ( 0xFF - 0x5B ) + WORD_FIELD_VALID_BIT); + mIgdOpRegion.OpRegion->MBox3.BCLM[9] = ( ( 73 << 8 ) + ( 0xFF - 0x44 ) + WORD_FIELD_VALID_BIT); + mIgdOpRegion.OpRegion->MBox3.BCLM[10] = ( ( 82 << 8 ) + ( 0xFF - 0x2D ) + WORD_FIELD_VALID_BIT); + mIgdOpRegion.OpRegion->MBox3.BCLM[11] = ( ( 91 << 8 ) + ( 0xFF - 0x16 ) + WORD_FIELD_VALID_BIT); + mIgdOpRegion.OpRegion->MBox3.BCLM[12] = ( (100 << 8 ) + ( 0xFF - 0x00 ) + WORD_FIELD_VALID_BIT); + + mIgdOpRegion.OpRegion->MBox3.PCFT = ((UINT32) GlobalNvsArea->Area->IgdPowerConservation) | BIT31; + // + // Create the notification and register callback function on the PciIo installation, + // + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + (EFI_EVENT_NOTIFY)GetVBiosVbtCallback, + NULL, + &mConOutEvent + ); + + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + + } + + Status = gBS->RegisterProtocolNotify ( +#ifdef ECP_FLAG + &gExitPmAuthProtocolGuid, +#else + &gEfiDxeSmmReadyToLockProtocolGuid, +#endif + mConOutEvent, + &gConOutNotifyReg + ); + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + (EFI_EVENT_NOTIFY)SetGOPVersionCallback, + NULL, + &mSetGOPverEvent + ); + + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->RegisterProtocolNotify ( + &gEfiGraphicsOutputProtocolGuid, + mSetGOPverEvent, + &gConOutNotifyReg + ); + + + // + // Initialize hardware state: + // Set ASLS Register to the OpRegion physical memory address. + // Set SWSCI register bit 15 to a "1" to activate SCI interrupts. + // + + IgdMmPci32 (IGD_ASLS_OFFSET) = (UINT32)(UINTN)(mIgdOpRegion.OpRegion); + IgdMmPci16AndThenOr (IGD_SWSCI_OFFSET, ~(BIT0), BIT15); + + DwordData = IgdMmPci32 (IGD_ASLS_OFFSET); + S3BootScriptSavePciCfgWrite ( + S3BootScriptWidthUint32, + (UINTN) (EFI_PCI_ADDRESS (IGD_BUS, IGD_DEV, IGD_FUN_0, IGD_ASLS_OFFSET)), + 1, + &DwordData + ); + + + DwordData = IgdMmPci32 (IGD_SWSCI_OFFSET); + S3BootScriptSavePciCfgWrite ( + S3BootScriptWidthUint32, + (UINTN) (EFI_PCI_ADDRESS (IGD_BUS, IGD_DEV, IGD_FUN_0, IGD_SWSCI_OFFSET)), + 1, + &DwordData + ); + + AcpiBase = MmPci16 ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_BASE + ) & B_PCH_LPC_ACPI_BASE_BAR; + + // + // Find the CPU I/O Protocol. ASSERT if not found. + // + Status = gBS->LocateProtocol ( + &gEfiCpuIoProtocolGuid, + NULL, + (void **)&CpuIo + ); + ASSERT_EFI_ERROR (Status); + + CpuIo->Io.Read ( + CpuIo, + EfiCpuIoWidthUint16, + AcpiBase + R_PCH_ACPI_GPE0a_STS, + 1, + &Data16 + ); + // + // Clear the B_PCH_ACPI_GPE0a_STS_GUNIT_SCI bit in R_PCH_ACPI_GPE0a_STS by writing a '1'. + // + Data16 |= B_PCH_ACPI_GPE0a_STS_GUNIT_SCI; + + CpuIo->Io.Write ( + CpuIo, + EfiCpuIoWidthUint16, + AcpiBase + R_PCH_ACPI_GPE0a_STS, + 1, + &Data16 + ); + + // + // Install OpRegion / Software SCI protocol + // + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gIgdOpRegionProtocolGuid, + &mIgdOpRegion, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Return final status + // + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/VlvPlatformInitDxe/IgdOpRegion.h b/Vlv2TbltDevicePkg/VlvPlatformInitDxe/IgdOpRegion.h new file mode 100644 index 0000000000..3cbaf53740 --- /dev/null +++ b/Vlv2TbltDevicePkg/VlvPlatformInitDxe/IgdOpRegion.h @@ -0,0 +1,240 @@ + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + IgdOpRegion.h + +Abstract: + + This is part of the implementation of an Intel Graphics drivers OpRegion / + Software SCI interface between system BIOS, ASL code, and Graphics drivers. + + Supporting Specifiction: OpRegion / Software SCI SPEC 0.70 + + Acronyms: + IGD: Internal Graphics Device + NVS: ACPI Non Volatile Storage + OpRegion: ACPI Operational Region + VBT: Video BIOS Table (OEM customizable data) + +--*/ + +#ifndef _IGD_OPREGION_H_ +#define _IGD_OPREGION_H_ + +// +// Statements that include other header files. +// +#include "VlvPlatformInit.h" +#include "VlvCommonDefinitions.h" +#include +#include + +// +// +// OpRegion (Miscellaneous) #defines. +// +// OpRegion Header #defines. +// + +#define HEADER_SIGNATURE "IntelGraphicsMem" +#define HEADER_SIZE 0x2000 +#define HEADER_OPREGION_VER 0x0200 +#define HEADER_OPREGION_REV 0x00 + +// +//For VLV Tablet, MailBOX2(SCI)is not supported. +// +#define HEADER_MBOX_SUPPORT (HD_MBOX4 + HD_MBOX3 + HD_MBOX1) +#define HD_MBOX1 BIT0 +#define HD_MBOX2 BIT1 +#define HD_MBOX3 BIT2 +#define HD_MBOX4 BIT3 +#define HD_MBOX5 BIT4 +#define SVER_SIZE 32 + +// +//Audio Type support for VLV2 A0 +// +#define AUDIO_TYPE_SUPPORT_MASK 0xFFFFFFF3 +#define NO_AUDIO_SUPPORT (0<<2) +#define HD_AUDIO_SUPPORT (1<<2) +#define LPE_AUDIO_SUPPORT (2<<2) +#define AUDIO_TYPE_FIELD_MASK 0xFFFFFFEF +#define AUDIO_TYPE_FIELD_VALID (1<<4) +#define AUDIO_TYPE_FIELD_INVALID (0<<4) + +// +// OpRegion Mailbox 1 EQUates. +// +// OpRegion Mailbox 3 EQUates. +// +#define ALS_ENABLE BIT0 +#define BLC_ENABLE BIT1 +#define BACKLIGHT_BRIGHTNESS 0xFF +#define FIELD_VALID_BIT BIT31 +#define WORD_FIELD_VALID_BIT BIT15 +#define PFIT_ENABLE BIT2 +#define PFIT_OPRN_AUTO 0x00000000 +#define PFIT_OPRN_SCALING 0x00000007 +#define PFIT_OPRN_OFF 0x00000000 +#define PFIT_SETUP_AUTO 0 +#define PFIT_SETUP_SCALING 1 +#define PFIT_SETUP_OFF 2 +#define INIT_BRIGHT_LEVEL 0x64 +#define PFIT_STRETCH 6 +#define PFIT_CENTER 1 + +// +// GMCH PCI register access #defines. +// + +#define IgdMmPci32(Register) MmPci32 (0, IGD_BUS, IGD_DEV, IGD_FUN_0, Register) +#define IgdMmPci16Or(Register, OrData) MmPci16Or (0, IGD_BUS, IGD_DEV, IGD_FUN_0, Register, OrData) +#define IgdMmPci16AndThenOr(Register,AndData,OrData) MmPci16AndThenOr (0, IGD_BUS, IGD_DEV, IGD_FUN_0, Register, AndData, OrData) + +// +// Video BIOS / VBT #defines +// +#define IGD_DID_VLV 0x0F31 +#define OPTION_ROM_SIGNATURE 0xAA55 +#define VBIOS_LOCATION_PRIMARY 0xC0000 + +#define VBT_SIGNATURE SIGNATURE_32 ('$', 'V', 'B', 'T') + +// +// Typedef stuctures +// +#pragma pack (1) +typedef struct { + UINT16 Signature; // 0xAA55 + UINT8 Size512; + UINT8 Reserved[21]; + UINT16 PcirOffset; + UINT16 VbtOffset; +} INTEL_VBIOS_OPTION_ROM_HEADER; +#pragma pack () + +#pragma pack (1) +typedef struct { + UINT32 Signature; // "PCIR" + UINT16 VendorId; // 0x8086 + UINT16 DeviceId; + UINT16 Reserved0; + UINT16 Length; + UINT8 Revision; + UINT8 ClassCode[3]; + UINT16 ImageLength; + UINT16 CodeRevision; + UINT8 CodeType; + UINT8 Indicator; + UINT16 Reserved1; +} INTEL_VBIOS_PCIR_STRUCTURE; +#pragma pack () + +#pragma pack (1) +typedef struct { + UINT8 HeaderSignature[20]; + UINT16 HeaderVersion; + UINT16 HeaderSize; + UINT16 HeaderVbtSize; + UINT8 HeaderVbtCheckSum; + UINT8 HeaderReserved; + UINT32 HeaderOffsetVbtDataBlock; + UINT32 HeaderOffsetAim1; + UINT32 HeaderOffsetAim2; + UINT32 HeaderOffsetAim3; + UINT32 HeaderOffsetAim4; + UINT8 DataHeaderSignature[16]; + UINT16 DataHeaderVersion; + UINT16 DataHeaderSize; + UINT16 DataHeaderDataBlockSize; + UINT8 CoreBlockId; + UINT16 CoreBlockSize; + UINT16 CoreBlockBiosSize; + UINT8 CoreBlockBiosType; + UINT8 CoreBlockReleaseStatus; + UINT8 CoreBlockHWSupported; + UINT8 CoreBlockIntegratedHW; + UINT8 CoreBlockBiosBuild[4]; + UINT8 CoreBlockBiosSignOn[155]; +} VBIOS_VBT_STRUCTURE; +#pragma pack () + +// +// Driver Private Function definitions +// +EFI_STATUS +GetSVER ( + OUT UINT8 *SVER + ); + +/** + Acquire the string associated with the ProducerGuid and return it. + + @param ProducerGuid The Guid to search the HII database for + @param Token The token value of the string to extract + @param String The string that is extracted + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_NOT_FOUND The requested string was not found + +**/ +EFI_STATUS +GetStringFromToken ( + IN EFI_GUID *ProducerGuid, + IN STRING_REF Token, + OUT CHAR16 **String + ); + +/** + + Graphics OpRegion / Software SCI driver installation function. + + @param Void + + @retval EFI_SUCCESS The driver installed without error. + @retval EFI_ABORTED The driver encountered an error and could not complete + installation of the ACPI tables. +**/ +EFI_STATUS +IgdOpRegionInit ( + void + ); + +/** + Extract information pertaining to the HiiHandle + + @param HiiHandle Hii handle + @param ImageLength For input, length of DefaultImage; + For output, length of actually required + + @param DefaultImage Image buffer prepared by caller + @param Guid Guid information about the form + + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_BUFFER_TOO_SMALL DefualtImage has no enough ImageLength + @retval EFI_SUCCESS Successfully extract data from Hii database. + +**/ +EFI_STATUS +ExtractDataFromHiiHandle ( + IN EFI_HII_HANDLE HiiHandle, + IN OUT UINT16 *ImageLength, + OUT UINT8 *DefaultImage, + OUT EFI_GUID *Guid + ); +#endif diff --git a/Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInit.c b/Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInit.c new file mode 100644 index 0000000000..5e8d95ae9f --- /dev/null +++ b/Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInit.c @@ -0,0 +1,292 @@ + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + VlvPlatformInit.c + +Abstract: + + This is the driver that initializes the Intel ValleyView. + +--*/ + +#include "VlvPlatformInit.h" +#include + +extern DXE_VLV_PLATFORM_POLICY_PROTOCOL *DxePlatformSaPolicy; +UINT64 GTTMMADR; + +DXE_VLV_PLATFORM_POLICY_PROTOCOL *DxePlatformSaPolicy; + +/** + "Poll Status" for GT Readiness + + @param Base Base address of MMIO + @param Offset MMIO Offset + @param Mask Mask + @param Result Value to wait for + + @retval None + +**/ +VOID +PollGtReady_hang ( + UINT64 Base, + UINT32 Offset, + UINT32 Mask, + UINT32 Result + ) +{ + UINT32 GtStatus; + + // + // Register read + // + GtStatus = MmioRead32 ((UINTN)Base+ Offset); + + while (((GtStatus & Mask) != Result)) { + + GtStatus = MmioRead32 ((UINTN)Base + Offset); + } + +} + +/** + Do Post GT PM Init Steps after VBIOS Initialization. + + @param Event A pointer to the Event that triggered the callback. + @param Context A pointer to private data registered with the callback function. + + @retval EFI_SUCCESS GC_TODO + + +**/ +EFI_STATUS +EFIAPI +PostPmInitCallBack ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT64 OriginalGTTMMADR; + UINT32 LoGTBaseAddress; + UINT32 HiGTBaseAddress; + + // + // Enable Bus Master, I/O and Memory access on 0:2:0 + // + PciOr8 (PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_CMD), (BIT2 | BIT1)); + + // + // only 32bit read/write is legal for device 0:2:0 + // + OriginalGTTMMADR = (UINT64) PciRead32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_GTTMMADR)); + OriginalGTTMMADR = LShiftU64 ((UINT64) PciRead32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_GTTMMADR + 4)), 32) | (OriginalGTTMMADR); + + // + // 64bit GTTMADR does not work for S3 save script table since it is executed in PEIM phase + // Program temporarily 32bits GTTMMADR for POST and S3 resume + // + LoGTBaseAddress = (UINT32) (GTTMMADR & 0xFFFFFFFF); + HiGTBaseAddress = (UINT32) RShiftU64 ((GTTMMADR & 0xFFFFFFFF00000000), 32); + S3PciWrite32(PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_GTTMMADR), LoGTBaseAddress); + S3PciWrite32(PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_GTTMMADR+4), HiGTBaseAddress); + + + + // + // Restore original GTTMMADR + // + LoGTBaseAddress = (UINT32) (OriginalGTTMMADR & 0xFFFFFFFF); + HiGTBaseAddress = (UINT32) RShiftU64 ((OriginalGTTMMADR & 0xFFFFFFFF00000000), 32); + + S3PciWrite32(PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_GTTMMADR), LoGTBaseAddress); + S3PciWrite32(PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_GTTMMADR+4), HiGTBaseAddress); + + + // + // Lock the following registers, GGC, BDSM, BGSM + // + PciOr32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_MGGC_OFFSET), LockBit); + PciOr32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_BSM_OFFSET), LockBit); + PciOr32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_BGSM), LockBit); + + gBS->CloseEvent (Event); + + // + // Return final status + // + return EFI_SUCCESS; +} + +/** + + Routine Description: + + Initialize GT Post Routines. + + @param ImageHandle Handle for the image of this driver + @param DxePlatformSaPolicy SA DxePlatformPolicy protocol + + @retval EFI_SUCCESS GT POST initialization complete + +**/ +EFI_STATUS +IgdPmHook ( + IN EFI_HANDLE ImageHandle, + IN DXE_VLV_PLATFORM_POLICY_PROTOCOL *DxePlatformSaPolicy + ) +{ + + EFI_EVENT mConOutEvent; + VOID *gConOutNotifyReg; + + EFI_STATUS Status; + + EFI_PHYSICAL_ADDRESS MemBaseAddress; + UINT32 LoGTBaseAddress; + UINT32 HiGTBaseAddress; + + GTTMMADR = 0; + Status = EFI_SUCCESS; + + // + // If device 0:2:0 (Internal Graphics Device, or GT) is enabled, then Program GTTMMADR, + // + if (PciRead16(PCI_LIB_ADDRESS(0, IGD_DEV, 0, IGD_R_VID)) != 0xFFFF) { + + ASSERT (gDS!=NULL); + + // + // Enable Bus Master, I/O and Memory access on 0:2:0 + // + PciOr8(PCI_LIB_ADDRESS(0, IGD_DEV, 0, IGD_R_CMD), (BIT2 | BIT1 | BIT0)); + + // + // Means Allocate 4MB for GTTMADDR + // + MemBaseAddress = 0x0ffffffff; + + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateMaxAddressSearchBottomUp, + EfiGcdMemoryTypeMemoryMappedIo, + GTT_MEM_ALIGN, + GTTMMADR_SIZE_4MB, + &MemBaseAddress, + ImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Program GT PM Settings if GTTMMADR allocation is Successful + // + GTTMMADR = (UINTN) MemBaseAddress; + + LoGTBaseAddress = (UINT32) (MemBaseAddress & 0xFFFFFFFF); + HiGTBaseAddress = (UINT32) RShiftU64 ((MemBaseAddress & 0xFFFFFFFF00000000), 32); + + PciWrite32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0, IGD_R_GTTMMADR), LoGTBaseAddress); + PciWrite32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0, IGD_R_GTTMMADR+4), HiGTBaseAddress); + + + S3PciRead32(PCI_LIB_ADDRESS(0, IGD_DEV, 0, IGD_R_GTTMMADR)); + + + S3MmioRead32(IGD_R_GTTMMADR + 4); + + + S3PciRead8(PCI_LIB_ADDRESS(0, IGD_DEV, 0, IGD_R_CMD)); + + // + // Do POST GT PM Init Steps after VBIOS Initialization in DoPostPmInitCallBack + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + (EFI_EVENT_NOTIFY)PostPmInitCallBack, + NULL, + &mConOutEvent + ); + + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + + Status = gBS->RegisterProtocolNotify ( + &gEfiGraphicsOutputProtocolGuid, + mConOutEvent, + &gConOutNotifyReg + ); + + + + MmioWrite64 (IGD_R_GTTMMADR, 0); + + // + // Free allocated resources + // + gDS->FreeMemorySpace ( + MemBaseAddress, + GTTMMADR_SIZE_4MB + ); + + } + + return EFI_SUCCESS; +} + +/** + + This is the standard EFI driver point that detects + whether there is an ICH southbridge in the system + and if so, initializes the chip. + + @param ImageHandle Handle for the image of this driver + @param SystemTable Pointer to the EFI System Table + + @retval EFI_SUCCESS The function completed successfully + +**/ +EFI_STATUS +EFIAPI +VlvPlatformInitEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gDxeVlvPlatformPolicyGuid, NULL, (void **)&DxePlatformSaPolicy); + ASSERT_EFI_ERROR (Status); + + // + // GtPostInit Initialization + // + DEBUG ((EFI_D_ERROR, "Initializing GT PowerManagement and other GT POST related\n")); + IgdPmHook (ImageHandle, DxePlatformSaPolicy); + + // + // IgdOpRegion Install Initialization + // + DEBUG ((EFI_D_ERROR, "Initializing IGD OpRegion\n")); + IgdOpRegionInit (); + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInit.h b/Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInit.h new file mode 100644 index 0000000000..7f7ed594c4 --- /dev/null +++ b/Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInit.h @@ -0,0 +1,70 @@ + +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + VlvPlatformInit.h + +Abstract: + + Header file for SA Initialization Driver. + +--*/ + +#ifndef _VLV_PLATFORM_INIT_DXE_H_ +#define _VLV_PLATFORM_INIT_DXE_H_ +#include "PiDxe.h" + +#include + +#include "IgdOpRegion.h" + +#include +#include +#include +#include "Library/DebugLib.h" +#include "Library/S3IoLib.h" +#include "Library/S3PciLib.h" +#include "Library/IoLib.h" +#include "Library/PciLib.h" +#include "Library/S3BootScriptLib.h" + +// +// GT RELATED EQUATES +// +#define GTT_MEM_ALIGN 22 +#define GTTMMADR_SIZE_4MB 0x400000 + +#define IGD_BUS 0x00 +#define IGD_DEV 0x02 +#define IGD_FUN_0 0x00 + +#define IGD_R_VID 0x00 +#define IGD_R_CMD 0x04 +#define IGD_R_GTTMMADR 0x10 + +#define IGD_R_BGSM 0x70 +#define LockBit BIT0 + +#define IGD_VID 0x8086 +#define IGD_DID 0xA001 +#define IGD_MGGC_OFFSET 0x0050 //GMCH Graphics Control Register 0x50 +#define IGD_BSM_OFFSET 0x005C //Base of Stolen Memory +#define IGD_SWSCI_OFFSET 0x00E0 //Software SCI 0xE0 2 +#define IGD_ASLE_OFFSET 0x00E4 //System Display Event Register 0xE4 4 +#define IGD_ASLS_OFFSET 0x00FC // ASL Storage + +#endif + diff --git a/Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInitDxe.inf b/Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInitDxe.inf new file mode 100644 index 0000000000..cea185fba8 --- /dev/null +++ b/Vlv2TbltDevicePkg/VlvPlatformInitDxe/VlvPlatformInitDxe.inf @@ -0,0 +1,79 @@ +# +# +#/*++ +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# Module Name: +# +# VlvPlatformInit.inf +# +# Abstract: +# +# Component description file for wrapper driver of Vlv platform init part. +# +#--*/ + + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VlvPlatformInitDxe + FILE_GUID = 1EC0EFC9-C93A-4b62-9B27-C059ABD80E92 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = VlvPlatformInitEntryPoint + +[Sources] + VlvPlatformInit.c + IgdOpRegion.c + + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + UefiBootServicesTableLib + S3BootScriptLib + DxeServicesTableLib + PchPlatformLib + S3PciLib + S3IoLib + PciLib + IoLib + +[Guids] + gBmpImageGuid + gEfiDxeServicesTableGuid + +[Protocols] + gDxeVlvPlatformPolicyGuid + gEfiDxeSmmReadyToLockProtocolGuid + gIgdOpRegionProtocolGuid + gEfiGlobalNvsAreaProtocolGuid + gEfiPciIoProtocolGuid + gEfiFirmwareVolumeProtocolGuid + gEfiCpuIoProtocolGuid + +[Depex] + gDxeVlvPlatformPolicyGuid AND + gEfiPciRootBridgeIoProtocolGuid AND + gEfiCpuIoProtocolGuid AND + gEfiDataHubProtocolGuid AND + gEfiGlobalNvsAreaProtocolGuid AND + gEfiFirmwareVolumeProtocolGuid AND + gEfiHiiDatabaseProtocolGuid + diff --git a/Vlv2TbltDevicePkg/Wpce791/LpcDriver.c b/Vlv2TbltDevicePkg/Wpce791/LpcDriver.c new file mode 100644 index 0000000000..be99b4c6d3 --- /dev/null +++ b/Vlv2TbltDevicePkg/Wpce791/LpcDriver.c @@ -0,0 +1,349 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + LpcDriver.c + +Abstract: + + EFI Lpc Driver for a Generic PC Platform + + + +--*/ + +#include "LpcDriver.h" +#include "IndustryStandard/Pci22.h" + +// +// This driver is for ACPI(PNP0A03,0)/PCI(0x1f,0) +// + +// +// Lpc Driver Global Variables +// + +EFI_DRIVER_BINDING_PROTOCOL gLpcDriver = { + LpcDriverSupported, + LpcDriverStart, + LpcDriverStop, + 0x10, + NULL, + NULL +}; + +LPC_DEV mLpc = { + LPC_DEV_SIGNATURE, + NULL, + { + IsaDeviceEnumerate, + IsaDeviceSetPower, + IsaGetCurrentResource, + IsaGetPossibleResource, + IsaSetResource, + IsaEnableDevice, + IsaInitDevice, + LpcInterfaceInit + }, + NULL +}; + +BOOLEAN InitExecuted = FALSE; + +/** + the entry point of the Lpc driver + +**/ +EFI_STATUS +EFIAPI +LpcDriverEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + + return EfiLibInstallDriverBinding (ImageHandle, SystemTable, &gLpcDriver, ImageHandle); +} + +/** + + ControllerDriver Protocol Method + +**/ +EFI_STATUS +EFIAPI +LpcDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *IsaBridgeDevicePath; + + ACPI_HID_DEVICE_PATH *AcpiNode; + PCI_DEVICE_PATH *PciNode; + PCI_TYPE00 Pci; + + // + // Get the ISA bridge's Device Path and test it + // the following code is specific + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **)&IsaBridgeDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = EFI_SUCCESS; + AcpiNode = (ACPI_HID_DEVICE_PATH *)IsaBridgeDevicePath; + if (AcpiNode->Header.Type != ACPI_DEVICE_PATH || + AcpiNode->Header.SubType != ACPI_DP || + DevicePathNodeLength (&AcpiNode->Header) != sizeof(ACPI_HID_DEVICE_PATH) || + AcpiNode -> HID != EISA_PNP_ID(0x0A03) || + AcpiNode -> UID != 0 ) { + Status = EFI_UNSUPPORTED; + } else { + // + // Get the next node + // + IsaBridgeDevicePath = NextDevicePathNode (IsaBridgeDevicePath); + PciNode = (PCI_DEVICE_PATH *)IsaBridgeDevicePath; + if (PciNode->Header.Type != HARDWARE_DEVICE_PATH || + PciNode->Header.SubType != HW_PCI_DP || + DevicePathNodeLength (&PciNode->Header) != sizeof (PCI_DEVICE_PATH) || + PciNode -> Function != 0x00 || + PciNode -> Device != 0x1f ) { + Status = EFI_UNSUPPORTED; + } + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Get PciIo protocol instance + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR(Status)) { + return Status; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof(Pci) / sizeof(UINT32), + &Pci + ); + + if (!EFI_ERROR (Status)) { + Status = EFI_SUCCESS; //TODO: force return success as temp solution EFI_UNSUPPORTED; + if ((Pci.Hdr.Command & 0x03) == 0x03) { + if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) { + // + // See if this is a standard PCI to ISA Bridge from the Base Code + // and Class Code + // + if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) { + Status = EFI_SUCCESS; + } else { + } + + // + // See if this is an Intel PCI to ISA bridge in Positive Decode Mode + // + if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE && + Pci.Hdr.VendorId == 0x8086 && + Pci.Hdr.DeviceId == 0x7110) { + Status = EFI_SUCCESS; + } else { + } + } else { + } + } + else { + } + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; +} + + +/** + Install EFI_ISA_ACPI_PROTOCOL + +**/ +EFI_STATUS +EFIAPI +LpcDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + LPC_DEV *LpcDev; + + + LpcDev = NULL; + + // + // Get Pci IO + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + mLpc.PciIo = PciIo; + + // + // Install IsaAcpi interface, the Sio interface is not installed! + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiIsaAcpiProtocolGuid, + &mLpc.IsaAcpi, + NULL + ); + return Status; +} + + +EFI_STATUS +EFIAPI +LpcDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_ISA_ACPI_PROTOCOL *IsaAcpi; + LPC_DEV *LpcDev; + + // + // Get EFI_ISA_ACPI_PROTOCOL interface + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIsaAcpiProtocolGuid, + (VOID **)&IsaAcpi, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + LpcDev = LPC_ISA_ACPI_FROM_THIS (IsaAcpi); + + // + // Uninstall protocol interface: EFI_ISA_ACPI_PROTOCOL + // + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiIsaAcpiProtocolGuid, + &LpcDev->IsaAcpi + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; +} + +VOID +LpcIoRead8 ( + IN UINT16 Port, + OUT UINT8 *Data + ) +{ + mLpc.PciIo->Io.Read( + mLpc.PciIo, + EfiPciWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + Port, + 1, + Data + ); +} + +VOID +LpcIoWrite8 ( + IN UINT16 Port, + IN UINT8 Data + ) +{ + mLpc.PciIo->Io.Write( + mLpc.PciIo, + EfiPciWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + Port, + 1, + &Data + ); +} + diff --git a/Vlv2TbltDevicePkg/Wpce791/LpcDriver.h b/Vlv2TbltDevicePkg/Wpce791/LpcDriver.h new file mode 100644 index 0000000000..d85c081af4 --- /dev/null +++ b/Vlv2TbltDevicePkg/Wpce791/LpcDriver.h @@ -0,0 +1,117 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + LpcDriver.h + +Abstract: + + EFI Lpc Driver for a Generic PC Platform + + + +--*/ + +#ifndef _LPC_DRIVER_H +#define _LPC_DRIVER_H + + #include "LpcSio.h" + #include "LpcIsaAcpi.h" + +#include "Protocol/IsaAcpi.h" +#include "Protocol/PciIo.h" +#include "Protocol/DriverBinding.h" +#include "Library/UefiBootServicesTableLib.h" +#include "IsaAcpiDxe/PcatIsaAcpi.h" +#include "IndustryStandard/Pci22.h" +#include "Protocol/LpcWpce791Policy.h" + +#include + +#define ICH_LPC_BRIDGE_BUS_DEV_FUNC 0x1F0000 + +// +// LPC device private data structure +// +//#define LPC_DEV_SIGNATURE 'W87X' +#define LPC_DEV_SIGNATURE SIGNATURE_32('X', '7', '8', 'W') //'W87X' +#define EFI_WPCE791_PS2_KEYBOARD_ENABLE 0x01 +#define EFI_WPCE791_PS2_KEYBOARD_DISABLE 0x00 + +#define EFI_WPCE791_PS2_MOUSE_ENABLE 0x01 +#define EFI_WPCE791_PS2_MOUSE_DISABLE 0x00 + + + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_ISA_ACPI_PROTOCOL IsaAcpi; + EFI_PCI_IO_PROTOCOL *PciIo; + +} LPC_DEV; + +#define LPC_ISA_ACPI_FROM_THIS(a) BASE_CR (a, LPC_DEV, IsaAcpi) + +// +// Driver entry point +// +EFI_STATUS +EFIAPI +LpcDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +// +// Prototypes for Driver model protocol interface +// +EFI_STATUS +EFIAPI +LpcDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +LpcDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +LpcDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +VOID +LpcIoRead8 ( + IN UINT16 Port, + OUT UINT8 *Data + ); + +VOID +LpcIoWrite8 ( + IN UINT16 Port, + IN UINT8 Data + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Wpce791/LpcIsaAcpi.c b/Vlv2TbltDevicePkg/Wpce791/LpcIsaAcpi.c new file mode 100644 index 0000000000..eeffced9cb --- /dev/null +++ b/Vlv2TbltDevicePkg/Wpce791/LpcIsaAcpi.c @@ -0,0 +1,371 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + LpcIsaAcpi.c + +Abstract: IsaAcpi implementation + + + +--*/ + +#include "LpcDriver.h" + +// +// PS/2 Keyboard Controller +// +static EFI_ISA_ACPI_RESOURCE mLpcWpce791Ps2KeyboardDeviceResources[] = { + {EfiIsaAcpiResourceIo, 0, 0x60, 0x64}, + {EfiIsaAcpiResourceInterrupt, 0, 1, 0}, + {EfiIsaAcpiResourceEndOfList, 0, 0, 0} +}; + +// +// PS/2 Mouse Controller +// +static EFI_ISA_ACPI_RESOURCE mLpcWpce791Ps2MouseDeviceResources[] = { + {EfiIsaAcpiResourceIo, 0, 0x60, 0x64}, + {EfiIsaAcpiResourceInterrupt, 0, 12, 0}, + {EfiIsaAcpiResourceEndOfList, 0, 0, 0} +}; + +// +// COM +// +static EFI_ISA_ACPI_RESOURCE mLpcWpce791ComDeviceResources[] = { + {EfiIsaAcpiResourceIo, 0, 0x3f8, 0x3ff}, + {EfiIsaAcpiResourceInterrupt, 0, 4, 0}, + {EfiIsaAcpiResourceEndOfList, 0, 0, 0} +}; + +// +// Table of ISA Controllers +// +EFI_ISA_ACPI_RESOURCE_LIST mLpcWpce791DeviceList[] = { + {{EISA_PNP_ID(0x303), 0}, mLpcWpce791Ps2KeyboardDeviceResources }, // PS/2 Keyboard Controller + {{EISA_PNP_ID(0xF03), 0}, mLpcWpce791Ps2MouseDeviceResources }, // PS/2 Mouse Controller + {{EISA_PNP_ID(0x501), 0}, mLpcWpce791ComDeviceResources }, // COM + {{0, 0}, NULL } // End +}; + +static ICH_DMA_INIT mIchDmaInitTable [] = { +// +//Register OFFSET, Value +// + + 0x0D8, 0x000, // Reset DMA Controller 2 + 0x0D0, 0x000, // Enable DMA controller 2 + 0x00C, 0x000, // Reset DMA Controller 1 + 0x008, 0x000, // Enable DMA controller 1 + + // + // Channel 4 + // + 0x0D6, 0x0c0, // DMA contr. 2 Cascade mode, addr. increment, disable auto init. + 0x0D2, 0x000, // Clear write request register + 0x0d4, 0x000, // Enable DREQs for channel + + // + // Channel 0 + // + 0x00B, 0x040, // DMA contr. 1 single mode, addr. increment, disable auto init. + 0x009, 0x000, // Clear write request register + 0x00A, 0x000, // Enable DREQs for channel + + // + // Channel 1 + // + 0x00B, 0x041, // DMA contr. 1 single mode, addr. increment, disable auto init. + 0x009, 0x001, // Clear write request register + 0x00A, 0x001, // Enable DREQs for channel + + // + // Channel 2 + // + 0x00B, 0x042, // DMA contr. 1 single mode, addr. increment, disable auto init. + 0x009, 0x002, // Clear write request register + 0x00A, 0x002, // Enable DREQs for channel + + // + // Channel 3 + // + 0x00B, 0x043, // DMA contr. 1 single mode, addr. increment, disable auto init. + 0x009, 0x003, // Clear write request register + 0x00A, 0x003, // Enable DREQs for channel + + // + // Channel 5 + // + 0x0D6, 0x041, // DMA contr. 2 single mode, addr. increment, disable auto init. + 0x0D2, 0x001, // Clear write request register + 0x0D4, 0x001, // Enable DREQs for channel + + // + // Channel 6 + // + 0x0D6, 0x042, // DMA contr. 2 single mode, addr. increment, disable auto init. + 0x0D2, 0x002, // Clear write request register + 0x0D4, 0x002, // Enable DREQs for channel + + // + // Channel 7 + // + 0x0D6, 0x043, // DMA contr. 2 single mode, addr. increment, disable auto init. + 0x0D2, 0x003, // Clear write request register + 0x0D4, 0x003 // Enable DREQs for channel + +}; + +// +// ISA ACPI Protocol Functions +// +/** + + Enumerate the ISA devices on the ISA bus + +**/ +VOID +IsaDeviceLookup ( + IN EFI_ISA_ACPI_DEVICE_ID *Device, + OUT EFI_ISA_ACPI_RESOURCE_LIST **IsaAcpiDevice, + OUT EFI_ISA_ACPI_RESOURCE_LIST **NextIsaAcpiDevice + ) +{ + UINTN Index; + + *IsaAcpiDevice = NULL; + if (NextIsaAcpiDevice != NULL) { + *NextIsaAcpiDevice = NULL; + } + if (Device == NULL) { + Index = 0; + } else { + for(Index = 0; mLpcWpce791DeviceList[Index].Device.HID != 0; Index++) { + if (Device->HID == mLpcWpce791DeviceList[Index].Device.HID && + Device->UID == mLpcWpce791DeviceList[Index].Device.UID ) { + break; + } + } + if (mLpcWpce791DeviceList[Index].Device.HID == 0) { + return; + } + *IsaAcpiDevice = &(mLpcWpce791DeviceList[Index]); + Index++; + } + if (NextIsaAcpiDevice != NULL && mLpcWpce791DeviceList[Index].Device.HID != 0){ + *NextIsaAcpiDevice = &(mLpcWpce791DeviceList[Index]); + } +} + + +/** + Enumerate the ISA devices on the ISA bus + It is hard code now and future it will get from ACPI table + +**/ +EFI_STATUS +EFIAPI +IsaDeviceEnumerate ( + IN EFI_ISA_ACPI_PROTOCOL *This, + OUT EFI_ISA_ACPI_DEVICE_ID **Device + ) +{ + EFI_ISA_ACPI_RESOURCE_LIST *IsaAcpiDevice; + EFI_ISA_ACPI_RESOURCE_LIST *NextIsaAcpiDevice; + + IsaDeviceLookup (*Device, &IsaAcpiDevice, &NextIsaAcpiDevice); + if (NextIsaAcpiDevice == NULL) { + return EFI_NOT_FOUND; + } + *Device = &(NextIsaAcpiDevice->Device); + return EFI_SUCCESS; +} + +/** + Set ISA device power use sio + +**/ +EFI_STATUS +EFIAPI +IsaDeviceSetPower ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN BOOLEAN OnOff + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Get current Resource of the specific ISA device + It is hardcode now and future will get from ACPI table + +**/ +EFI_STATUS +EFIAPI +IsaGetCurrentResource ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList + ) +{ + IsaDeviceLookup (Device, ResourceList, NULL); + if (*ResourceList == NULL || (*ResourceList)->ResourceItem == NULL) { + return EFI_NOT_FOUND; + } + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +IsaGetPossibleResource ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList + ) +{ + // + // Not supported yet + // + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +IsaSetResource ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN EFI_ISA_ACPI_RESOURCE_LIST *ResourceList + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +IsaEnableDevice ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN BOOLEAN Enable + ) +{ + + return EFI_UNSUPPORTED; +} + +/** + + Clear out Resource List if device is set to disable by platform policy + +**/ +VOID +EmptyResourceList ( + IN UINT32 DeviceHid + ) +{ + UINT8 Index; + for (Index = 0; mLpcWpce791DeviceList[Index].Device.HID != 0; Index++) { + if (DeviceHid == mLpcWpce791DeviceList[Index].Device.HID) { + mLpcWpce791DeviceList[Index].ResourceItem = NULL; + } + } + return; +} + +/** + + Clear out Resource List if device is set to disable by platform policy + +**/ +VOID +EmptyResourceListHidUid ( + IN UINT32 DeviceHid, + IN UINT32 DeviceUid + ) +{ + UINT8 Index; + for (Index = 0; mLpcWpce791DeviceList[Index].Device.HID != 0; Index++) { + if ((DeviceHid == mLpcWpce791DeviceList[Index].Device.HID) && + (DeviceUid == mLpcWpce791DeviceList[Index].Device.UID)) { + mLpcWpce791DeviceList[Index].ResourceItem = NULL; + } + } + return; +} + +EFI_STATUS +EFIAPI +IsaInitDevice ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device + ) +{ + EFI_WPCE791_POLICY_PROTOCOL *LpcWpce791Policy; + EFI_STATUS Status; + + // + // Disable configuration according to platform protocol + // + Status = gBS->LocateProtocol ( + &gEfiLpcWpce791PolicyProtocolGuid, + NULL, + (VOID **) &LpcWpce791Policy + ); + if (!EFI_ERROR(Status)) { + if (LpcWpce791Policy->DeviceEnables.Ps2Keyboard == EFI_WPCE791_PS2_KEYBOARD_DISABLE) { + EmptyResourceList(EISA_PNP_ID(0x303)); + DisableLogicalDevice (SIO_KEYBOARD); + EmptyResourceList(EISA_PNP_ID(0xF03)); + DisableLogicalDevice (SIO_KEYBOARD); + } + if (LpcWpce791Policy->DeviceEnables.Ps2Mouse == EFI_WPCE791_PS2_MOUSE_DISABLE) { + EmptyResourceList(EISA_PNP_ID(0xF03)); + DisableLogicalDevice (SIO_MOUSE); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +LpcInterfaceInit ( + IN EFI_ISA_ACPI_PROTOCOL *This + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN Index; + + PciIo = (LPC_ISA_ACPI_FROM_THIS (This))->PciIo; + + // + // DMA controller initialize + // + for (Index=0; Index < (sizeof(mIchDmaInitTable)/sizeof(ICH_DMA_INIT)); Index++) { + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + mIchDmaInitTable[Index].Register, + 1, + &mIchDmaInitTable[Index].Value + ); + } + + return EFI_SUCCESS; +} + diff --git a/Vlv2TbltDevicePkg/Wpce791/LpcIsaAcpi.h b/Vlv2TbltDevicePkg/Wpce791/LpcIsaAcpi.h new file mode 100644 index 0000000000..54bbba80d2 --- /dev/null +++ b/Vlv2TbltDevicePkg/Wpce791/LpcIsaAcpi.h @@ -0,0 +1,108 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + LpcIsaAcpi.h + +Abstract: + + Isa Acpi interface + + + +--*/ + +#ifndef _LPC_ISA_ACPI_H +#define _LPC_ISA_ACPI_H + + + +#include "Protocol/IsaAcpi.h" +#include "Library/DevicePathLib.h" + + +typedef struct { + UINT8 Register; + UINT8 Value; +} ICH_DMA_INIT; + +// +// Prototypes for the ISA ACPI protocol interface +// +EFI_STATUS +EFIAPI +IsaDeviceEnumerate ( + IN EFI_ISA_ACPI_PROTOCOL *This, + OUT EFI_ISA_ACPI_DEVICE_ID **Device + ); + +EFI_STATUS +EFIAPI +IsaDeviceSetPower ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN BOOLEAN OnOff + ); + +EFI_STATUS +EFIAPI +IsaGetCurrentResource ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList + ); + +EFI_STATUS +EFIAPI +IsaGetPossibleResource ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList + ); + +EFI_STATUS +EFIAPI +IsaSetResource ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN EFI_ISA_ACPI_RESOURCE_LIST *ResourceList + ); + +EFI_STATUS +EFIAPI +IsaEnableDevice ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN BOOLEAN Enable + ); + +EFI_STATUS +EFIAPI +IsaInitDevice ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device + ); + +EFI_STATUS +EFIAPI +LpcInterfaceInit ( + IN EFI_ISA_ACPI_PROTOCOL *This +); + +VOID +EmptyResourceList ( + IN UINT32 DeviceHid +); + +#endif diff --git a/Vlv2TbltDevicePkg/Wpce791/LpcSio.c b/Vlv2TbltDevicePkg/Wpce791/LpcSio.c new file mode 100644 index 0000000000..8446d381f7 --- /dev/null +++ b/Vlv2TbltDevicePkg/Wpce791/LpcSio.c @@ -0,0 +1,131 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + +Module Name: + + LpcSio.c + +Abstract: Sio implementation + +Revision History + +--*/ + +#include "LpcDriver.h" +#include + +VOID +WriteRegister ( + IN UINT8 Index, + IN UINT8 Data + ); + +typedef struct { + UINT8 Register; + UINT8 Value; +} EFI_SIO_TABLE; + +EFI_SIO_TABLE mSioTable[] = { + // + // Init keyboard controller + // + { REG_LOGICAL_DEVICE, SIO_KEYBOARD }, + { BASE_ADDRESS_HIGH, 0x00 }, + { BASE_ADDRESS_LOW, 0x60 }, + { BASE_ADDRESS_HIGH2, 0x00 }, + { BASE_ADDRESS_LOW2, 0x64 }, + { PRIMARY_INTERRUPT_SELECT, 0x01 }, + { ACTIVATE, 0x1 }, + + // + // Init Mouse controller + // + { REG_LOGICAL_DEVICE, SIO_MOUSE }, + { BASE_ADDRESS_HIGH, 0x00 }, + { BASE_ADDRESS_LOW, 0x60 }, + { BASE_ADDRESS_HIGH2, 0x00 }, + { BASE_ADDRESS_LOW2, 0x64 }, + { PRIMARY_INTERRUPT_SELECT, 0x0c }, + { ACTIVATE, 0x1 }, + + { REG_LOGICAL_DEVICE, SIO_COM }, + { BASE_ADDRESS_HIGH, 0x03 }, + { BASE_ADDRESS_LOW, 0xf8 }, + { PRIMARY_INTERRUPT_SELECT, 0x04 }, + { ACTIVATE, 0x1 }, + + +}; + +VOID +LPCWPCE791SetDefault () +{ + UINT8 Index; + + for (Index = 0; Index < sizeof(mSioTable)/sizeof(EFI_SIO_TABLE); Index++) { + WriteRegisterAndSaveToScript (mSioTable[Index].Register, mSioTable[Index].Value); + } + + return; +} + +VOID +DisableLogicalDevice ( + UINT8 DeviceId + ) +{ + WriteRegisterAndSaveToScript (REG_LOGICAL_DEVICE, DeviceId); + WriteRegisterAndSaveToScript (ACTIVATE, 0); + WriteRegisterAndSaveToScript (BASE_ADDRESS_HIGH, 0); + WriteRegisterAndSaveToScript (BASE_ADDRESS_LOW, 0); + + return; +} + +VOID +WriteRegister ( + IN UINT8 Index, + IN UINT8 Data + ) +{ + LpcIoWrite8(CONFIG_PORT, Index); + LpcIoWrite8(DATA_PORT, Data); + + return; +} + +VOID +WriteRegisterAndSaveToScript ( + IN UINT8 Index, + IN UINT8 Data + ) +{ + UINT8 Buffer[2]; + + LpcIoWrite8(CONFIG_PORT, Index); + LpcIoWrite8(DATA_PORT, Data); + + Buffer[0] = Index; + Buffer[1] = Data; + S3BootScriptSaveIoWrite ( + EfiBootScriptWidthUint8, + INDEX_PORT, + 2, + Buffer + ); + + return; +} + diff --git a/Vlv2TbltDevicePkg/Wpce791/LpcSio.h b/Vlv2TbltDevicePkg/Wpce791/LpcSio.h new file mode 100644 index 0000000000..f54bc7a8d1 --- /dev/null +++ b/Vlv2TbltDevicePkg/Wpce791/LpcSio.h @@ -0,0 +1,106 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + LpcSio.h + +Abstract: + + Lpc driver's sio interface + + + +--*/ + +#ifndef _LPC_SIO_H +#define _LPC_SIO_H + +#include "Protocol/PciRootBridgeIo.h" + +#define VARSIOINSTALLED L"VarSIOProcotolInstalled" + +// +// Port address +// +#define CONFIG_PORT 0x04E +#define INDEX_PORT 0x04E +#define DATA_PORT INDEX_PORT + 1 + +// +// Logical Device +// +#define SIO_COM 0x3 +#define SIO_MSWC 0x4 +#define SIO_MOUSE 0x5 +#define SIO_KEYBOARD 0x6 +#define SIO_SHM 0xF +#define SIO_PM1 0x11 +#define SIO_PM2 0x12 +#define SIO_PM3 0x17 +#define SIO_ESHM 0x1D + +// +// Global register +// +#define REG_LOGICAL_DEVICE 0x07 +#define REG_DEVICE_ID 0x20 +#define SIO_CONFIG_1 0x21 +#define REG_CHIP_REV 0x24 +#define SIO_CONFIG_5 0x25 +#define SIO_CONFIG_6 0x26 +#define REG_DEVICE_REV 0x27 +#define SIO_CONFIG_9 0x29 +#define SIO_CONFIG_D 0x2D + +#define ACTIVATE 0x30 +#define BASE_ADDRESS_HIGH 0x60 +#define BASE_ADDRESS_LOW 0x61 +#define BASE_ADDRESS_HIGH2 0x62 +#define BASE_ADDRESS_LOW2 0x63 +#define PRIMARY_INTERRUPT_SELECT 0x70 +#define DMA_CHANNEL_SELECT 0x74 + +EFI_STATUS +InitializeLpcSio ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RootBridgeIo + ); + +// +// Prototypes for the sio internal function +// +// +// Internal function +// +VOID +LPCWPCE791SetDefault ( + VOID + ); + +VOID +WriteRegisterAndSaveToScript ( + IN UINT8 Index, + IN UINT8 Data + ); + +VOID +FloppyWriteProtect ( + VOID + ); + +VOID +DisableLogicalDevice ( + UINT8 DeviceId + ); + +#endif diff --git a/Vlv2TbltDevicePkg/Wpce791/Wpce791.inf b/Vlv2TbltDevicePkg/Wpce791/Wpce791.inf new file mode 100644 index 0000000000..0296d09cf6 --- /dev/null +++ b/Vlv2TbltDevicePkg/Wpce791/Wpce791.inf @@ -0,0 +1,68 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# +# +# Module Name: +# +# SiO791.inf +# +# Abstract: +# +# Component description file for SIO791 module. +# +--*/ + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = SIO791 + FILE_GUID = 04A76C80-06B9-445e-B73E-CB8C61A6A964 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = LpcDriverEntryPoint + +[sources.common] + LpcIsaAcpi.h + LpcSio.h + LpcDriver.h + LpcIsaAcpi.c + LpcSio.c + LpcDriver.c + +[Packages] + MdePkg/MdePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + PcAtChipsetPkg/PcAtChipsetPkg.dec + + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + DevicePathLib + UefiLib + S3BootScriptLib + DebugLib + +[Ppis] + +[Protocols] + gEfiPciIoProtocolGuid + gEfiIsaAcpiProtocolGuid + gEfiLpcWpce791PolicyProtocolGuid + +[Guids] + +[Depex] + TRUE diff --git a/Vlv2TbltDevicePkg/bldX64.bat b/Vlv2TbltDevicePkg/bldX64.bat new file mode 100644 index 0000000000..afda8c89af --- /dev/null +++ b/Vlv2TbltDevicePkg/bldX64.bat @@ -0,0 +1,222 @@ +@REM @file +@REM Windows batch file to build BIOS ROM +@REM +@REM Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+@REM This program and the accompanying materials +@REM are licensed and made available under the terms and conditions of the BSD License +@REM which accompanies this distribution. The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php +@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 + +@echo off +@echo. +@time /t + +@if exist %WORKSPACE%\edk2.log del %WORKSPACE%\edk2.log +@if exist %WORKSPACE%\unitool.log del %WORKSPACE%\unitool.log +@if exist %WORKSPACE%\Conf\build_rule.txt del %WORKSPACE%\Conf\build_rule.txt +@if exist %WORKSPACE%\Conf\FrameworkDatabase.db del %WORKSPACE%\Conf\FrameworkDatabase.db +@if exist %WORKSPACE%\Conf\target.txt del %WORKSPACE%\Conf\target.txt +@if exist %WORKSPACE%\Conf\tools_def.txt del %WORKSPACE%\Conf\tools_def.txt +@if exist conf\.cache rmdir /q /s conf\.cache + +@set target=DEBUG + +@if /i "%1" == "release" set TARGET=RELEASE +@if /i "%2" == "release" set TARGET=RELEASE +@if /i "%3" == "release" set TARGET=RELEASE +@if /i "%4" == "release" set TARGET=RELEASE +@if /i "%5" == "release" set TARGET=RELEASE + +@set PlatformType=NO_PLATFORM +@set config_file=.\Vlv2TbltDevicePkg\PlatformPkgConfig.dsc +@set EVN_debug_file=.\Vlv2TbltDevicePkg\BiosIdx64D.env +@set EVN_release_file=.\Vlv2TbltDevicePkg\BiosIdx64R.env +@set auto_config_inc=.\Vlv2TbltDevicePkg\AutoPlatformCFG.txt + +@if "%1" == "MNW2" ( + set %PlatformType% = MNW2 + @echo Setting Baley Bay platform configration and BIOS ID ... + findstr /b /v BOARD_ID %EVN_debug_file% > newfile.env + echo BOARD_ID = MNW2MAX >> newfile.env + type newfile.env > %EVN_debug_file% + findstr /b /v BOARD_ID %EVN_release_file% > newfile.env + echo BOARD_ID = MNW2MAX >> newfile.env + type newfile.env > %EVN_release_file% + echo DEFINE ENBDT_PF_BUILD = TRUE >> %auto_config_inc% + echo DEFINE X64_CONFIG = TRUE >> %auto_config_inc% + goto PLATFORM_SETTING_DONE +) + +@if "%PlatformType%" == "NO_PLATFORM" ( + goto BldFail +) + +rem clearup the temp file +:PLATFORM_SETTING_DONE +@DEL NEWFILE.ENV +@DEL NEWFILE.CFG + +@REM Define platform specific environment variables. +@REM +@set PLATFORM_PACKAGE=Vlv2TbltDevicePkg +@set SCRIPT_ERROR=0 + +@REM Set basic environment. +@echo. +@echo Run edksetup.bat batch file. +@echo. +@del Conf\build_rule.txt +@REM @del Conf\tools_def.txt +@call edksetup.bat + + +@echo. +@echo Set the VS2008 environment. +@echo. +@if defined VS90COMNTOOLS ( + if not defined VSINSTALLDIR call "%VS90COMNTOOLS%\vsvars32.bat" + if /I "%VS90COMNTOOLS%" == "C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\" ( + set TOOL_CHAIN_TAG=VS2008 + ) else ( + set TOOL_CHAIN_TAG=VS2008x86 + ) +) else ( + echo. + echo !!! ERROR !!! VS2008 not installed correctly. VS90COMNTOOLS not defined. !!! + echo. + set SCRIPT_ERROR=1 + goto :BldEnd +) + +@echo. +@echo Set build environment. +@echo. +@if not exist Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG% ( + mkdir Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG% +) + + +@REM Set clean build option +@set CLEAN_BUILD_OPTION=-e + +@findstr /V "ACTIVE_PLATFORM TARGET TARGET_ARCH TOOL_CHAIN_TAG BUILD_RULE_CONF" Conf\target.txt > Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\target.txt + +@echo ACTIVE_PLATFORM = %PLATFORM_PACKAGE%/PlatformPkgX64.dsc >> Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\target.txt +@echo TARGET = %TARGET% >> Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\target.txt +@echo TARGET_ARCH = IA32 X64 >> Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\target.txt +@echo TOOL_CHAIN_TAG = %TOOL_CHAIN_TAG% >> Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\target.txt +@echo BUILD_RULE_CONF = Conf/build_rule.txt >> Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\target.txt +@move /Y Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\target.txt Conf + + + +@echo. +@echo Create BiosIdx64. +@echo. +@if not exist Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\X64 ( + mkdir Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\X64 +) + +@if "%TARGET%" == "DEBUG" ( + set BIOS_ID_FILE=BiosIdx64D.env + +) else ( + set BIOS_ID_FILE=BiosIdx64R.env + +) + + +GenBiosId.exe -i %PLATFORM_PACKAGE%\%BIOS_ID_FILE% -o Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\X64\BiosId.bin +@if %ERRORLEVEL% NEQ 0 goto BldFail + +@echo off +echo Copy reference code ASL files. + + +@if /i "/s" == "%1" goto BldSilent +@if /i "/s" == "%2" goto BldSilent +@if /i "/s" == "%3" goto BldSilent +@if /i "/s" == "%4" goto BldSilent +@if /i "/s" == "%5" goto BldSilent + +build -n %NUMBER_OF_PROCESSORS% +@if %ERRORLEVEL% NEQ 0 goto BldFail + +@If %SCRIPT_ERROR% EQU 1 goto BldFail +@goto BldSuccess + +:BldSilent + +build -n %NUMBER_OF_PROCESSORS% 1>>EDK2.log 2>&1 +@if %ERRORLEVEL% NEQ 0 goto BldFail + + +@If %SCRIPT_ERROR% EQU 1 goto BldFail + +:BldSuccess +@echo off +del Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\FV\VlvX64.beforeconfig.fd 1>>EDK2.log 2>&1 +del Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\FV\HiiDefaultData.txt 1>>EDK2.log 2>&1 +copy /y Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\FV\Vlv.fd Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\FV\VlvX64.beforeconfig.fd 1>>EDK2.log 2>&1 + +@echo. +@echo Extract setup default value from VFR (Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\FV\HiiDefaultData.txt) +@echo. +fce read -i Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\FV\VlvX64.beforeconfig.fd > Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\FV\HiiDefaultData.txt + + +@echo Update FD with default Hii value successfully! (both 'Setup' and 'SetupDefault') +@echo. +fce mirror -i Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\FV\VlvX64.beforeconfig.fd -o Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\FV\VlvX64.fd Setup SetupDefault 1>>EDK2.log 2>&1 + +@echo off +del Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\FV\Vlv.fd +del Vlv2TbltDevicePkg\RomImage\bios.rom +if not exist Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\ROM goto Gen8MImage +del /q /f Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\ROM\* +rd /Q Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\ROM +:Gen8MImage + +copy /b Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\FV\VlvX64.fd Vlv2TbltDevicePkg\RomImage\bios.rom + +pushd Vlv2TbltDevicePkg\RomImage\ +@if "%TARGET%" == "DEBUG" ( + call signbiosX64_debug.bat +) else ( + call signbiosX64_release.bat +) + +call ftoolbuild.bat +call ftoolbuild_sec_enable.bat +popd + +@echo off +mkdir Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\ROM +move Vlv2TbltDevicePkg\RomImage\SPI_Image\* Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\ROM\ > NUL + +call GenBIOS.bat X64 + +@echo on + +@echo TARGET: %TARGET% +@echo TOOL_CHAIN_TAG: %TOOL_CHAIN_TAG% +@echo BIOS location: Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\FV +@echo SPI Images location: Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG%\ROM +@echo. +@echo The EDKII BIOS build has successfully completed! +@echo. +@goto BldEnd + +:BldFail +@echo. +@echo The EDKII BIOS Build has failed! +@echo. +exit /b 1 + +:BldEnd +@time /t +exit /b 0 diff --git a/Vlv2TbltDevicePkg/bld_vlv.bat b/Vlv2TbltDevicePkg/bld_vlv.bat new file mode 100644 index 0000000000..b9c86e3569 --- /dev/null +++ b/Vlv2TbltDevicePkg/bld_vlv.bat @@ -0,0 +1,263 @@ +@REM @file +@REM Windows batch file to build BIOS ROM +@REM +@REM Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+@REM This program and the accompanying materials +@REM are licensed and made available under the terms and conditions of the BSD License +@REM which accompanies this distribution. The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php +@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 + +@echo off +setlocal EnableDelayedExpansion EnableExtensions +echo. +echo %date% %time% +echo. + +::********************************************************************** +:: Initial Setup +::********************************************************************** +set WORKSPACE=%CD% +if %WORKSPACE:~-1%==\ set WORKSPACE=%WORKSPACE:~0,-1% +set /a build_threads=1 +set "Build_Flags= " +set exitCode=0 +set Arch=X64 +set Source=0 + +:: Clean up previous build files. +if exist %WORKSPACE%\edk2.log del %WORKSPACE%\edk2.log +if exist %WORKSPACE%\unitool.log del %WORKSPACE%\unitool.log +if exist %WORKSPACE%\Conf\target.txt del %WORKSPACE%\Conf\target.txt +if exist %WORKSPACE%\Conf\tools_def.txt del %WORKSPACE%\Conf\tools_def.txt +if exist %WORKSPACE%\Conf\build_rule.txt del %WORKSPACE%\Conf\build_rule.txt +if exist %WORKSPACE%\Conf\FrameworkDatabase.db del %WORKSPACE%\Conf\FrameworkDatabase.db +if exist conf\.cache rmdir /q/s conf\.cache + +:: Setup EDK environment. Edksetup puts new copies of target.txt, tools_def.txt, build_rule.txt in WorkSpace\Conf +:: Also run edksetup as soon as possible to avoid it from changing environment variables we're overriding +call edksetup.bat > nul +@echo off + +:: Define platform specific environment variables. +set PLATFORM_PACKAGE=Vlv2TbltDevicePkg +set config_file=.\%PLATFORM_PACKAGE%\PlatformPkgConfig.dsc +set auto_config_inc=.\%PLATFORM_PACKAGE%\AutoPlatformCFG.txt + +set EDK_SOURCE=%WORKSPACE%\EdkCompatibilityPkg + +::create new AutoPlatformCFG.txt file +copy /y nul %auto_config_inc% >nul + +::********************************************************************** +:: Parse command line arguments +::********************************************************************** + +:: Optional arguments +:OptLoop +if /i "%~1"=="/?" goto Usage + +if /i "%~1"=="/l" ( + set Build_Flags=%Build_Flags% -j EDK2.log + shift + goto OptLoop +) +if /i "%~1" == "/c" ( + echo Removing previous build files ... + if exist build ( + del /f/s/q build > null + rmdir /s/q build + ) + if exist conf\.cache ( + del /f/s/q conf\.cache > null + rmdir /s/q conf\.cache + ) + echo. + shift + goto OptLoop +) + +if /i "%~1"=="/x64" ( + set Arch=X64 + shift + goto OptLoop +) +if /i "%~1"=="/IA32" ( + set Arch=IA32 + shift + goto OptLoop +) + +:: Required argument(s) +if "%~1"=="" goto Usage + +::Remove the values for Platform_Type and Build_Target from BiosIdX.env and stage in Conf\ +if "%Arch%"=="IA32" ( + findstr /b /v "BOARD_ID BUILD_TYPE" %PLATFORM_PACKAGE%\BiosIdR.env > Conf\BiosId.env + echo DEFINE X64_CONFIG = FALSE >> %auto_config_inc% +) else if "%Arch%"=="X64" ( + findstr /b /v "BOARD_ID BUILD_TYPE" %PLATFORM_PACKAGE%\BiosIdx64R.env > Conf\BiosId.env + echo DEFINE X64_CONFIG = TRUE >> %auto_config_inc% +) + +:: -- Build flags settings for each Platform -- +echo Setting %1 platform configuration and BIOS ID... +if /i "%~1" == "MNW2" ( + echo BOARD_ID = MNW2MAX >> %Conf\BiosId.env + echo DEFINE ENBDT_PF_BUILD = TRUE >> %auto_config_inc% + +) else ( + echo Error - Unsupported PlatformType: %1 + goto Usage +) +set Platform_Type=%~1 + +if /i "%~2" == "RELEASE" ( + set target=RELEASE + echo BUILD_TYPE = R >> Conf\BiosId.env +) else ( + set target=DEBUG + echo BUILD_TYPE = D >> Conf\BiosId.env +) + +::********************************************************************** +:: Additional EDK Build Setup/Configuration +::********************************************************************** +echo. +echo Setting the Build environment for VS2008/VS2010... +if defined VS90COMNTOOLS ( + if not defined VSINSTALLDIR call "%VS90COMNTOOLS%\vsvars32.bat" + if /I "%VS90COMNTOOLS%" == "C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\" ( + set TOOL_CHAIN_TAG=VS2008 + ) else ( + set TOOL_CHAIN_TAG=VS2008x86 + ) + ) else if defined VS100COMNTOOLS ( + if not defined VSINSTALLDIR call "%VS100COMNTOOLS%\vsvars32.bat" + if /I "%VS100COMNTOOLS%" == "C:\Program Files\Microsoft Visual Studio 10.0\Common7\Tools\" ( + set TOOL_CHAIN_TAG=VS2010 +) else ( + set TOOL_CHAIN_TAG=VS2010x86 + ) +) else ( + echo --ERROR: VS2008/VS2010 not installed correctly. VS90COMNTOOLS/VS100COMNTOOLS not defined ^^! + echo. + goto :BldFail +) + +echo Ensuring correct build directory is present for GenBiosId... +set BUILD_PATH=Build\%PLATFORM_PACKAGE%\%TARGET%_%TOOL_CHAIN_TAG% + +echo Modifing Conf files for this build... +:: Remove lines with these tags from target.txt +findstr /V "TARGET TARGET_ARCH TOOL_CHAIN_TAG BUILD_RULE_CONF ACTIVE_PLATFORM MAX_CONCURRENT_THREAD_NUMBER" Conf\target.txt > Conf\target.txt.tmp + +echo TARGET = %TARGET% >> Conf\target.txt.tmp +if "%Arch%"=="IA32" ( + echo TARGET_ARCH = IA32 >> Conf\target.txt.tmp +) else if "%Arch%"=="X64" ( + echo TARGET_ARCH = IA32 X64 >> Conf\target.txt.tmp +) +echo TOOL_CHAIN_TAG = %TOOL_CHAIN_TAG% >> Conf\target.txt.tmp +echo BUILD_RULE_CONF = Conf/build_rule.txt >> Conf\target.txt.tmp +if %Source% == 0 ( + echo ACTIVE_PLATFORM = %PLATFORM_PACKAGE%/PlatformPkg%Arch%.dsc >> Conf\target.txt.tmp +) else ( + echo ACTIVE_PLATFORM = %PLATFORM_PACKAGE%/PlatformPkg%Arch%Source.dsc >> Conf\target.txt.tmp +) +echo MAX_CONCURRENT_THREAD_NUMBER = %build_threads% >> Conf\target.txt.tmp + +move /Y Conf\target.txt.tmp Conf\target.txt >nul + +::********************************************************************** +:: Build BIOS +::********************************************************************** + +echo Creating BiosId... +pushd %PLATFORM_PACKAGE% +if not exist ..\%BUILD_PATH%\IA32 mkdir ..\%BUILD_PATH%\IA32 + GenBiosId.exe -i ..\Conf\BiosId.env -o ..\%BUILD_PATH%\IA32\BiosId.bin -ob ..\Conf\BiosId.bat +if "%Arch%"=="X64" ( + if not exist ..\%BUILD_PATH%\X64 mkdir ..\%BUILD_PATH%\X64 + GenBiosId.exe -i ..\Conf\BiosId.env -o ..\%BUILD_PATH%\X64\BiosId.bin -ob ..\Conf\BiosId.bat +) +popd + + +if %ERRORLEVEL% NEQ 0 goto BldFail + +echo. +echo Invoking EDK2 build... +build %Build_Flags% + +if %ERRORLEVEL% NEQ 0 goto BldFail + +::********************************************************************** +:: Post Build processing and cleanup +::********************************************************************** + +echo Running fce... + +pushd %PLATFORM_PACKAGE% +:: Extract Hii data from build and store in HiiDefaultData.txt +fce read -i ..\%BUILD_PATH%\FV\Vlv.fd > ..\%BUILD_PATH%\FV\HiiDefaultData.txt 1>>EDK2.log 2>&1 + +:: copy the Setup variable to the SetupDefault variable and save changes to VlvXXX.fd +fce mirror -i ..\%BUILD_PATH%\FV\Vlv.fd -o ..\%BUILD_PATH%\FV\Vlv%Arch%.fd Setup SetupDefault 1>>EDK2.log 2>&1 + +popd + +if %ERRORLEVEL% NEQ 0 goto BldFail +::echo FD successfully updated with default Hii values. + +:: Set the Board_Id, Build_Type, Version_Major, and Version_Minor environment variables +find /v "#" Conf\BiosId.env > ver_strings +for /f "tokens=1,3" %%i in (ver_strings) do set %%i=%%j +del /f/q ver_strings >nul + +set BIOS_Name=%BOARD_ID%_%Arch%_%BUILD_TYPE%_%VERSION_MAJOR%_%VERSION_MINOR%.ROM +copy /y/b %BUILD_PATH%\FV\Vlv%Arch%.fd %WORKSPACE%\%BIOS_Name% >nul + +echo. +echo Build location: %BUILD_PATH% +echo BIOS ROM Created: %BIOS_Name% +echo. +echo -------------------- The EDKII BIOS build has successfully completed. -------------------- +echo. +goto Exit + +:Usage +echo. +echo *************************************************************************** +echo Build BIOS rom for VLV platforms. +echo. +echo Usage: bld_vlv.bat [options] PlatformType [Build Target] +echo. +echo /c CleanAll before building +echo /IA32 Set Arch to IA32 (default: X64) +echo /X64 Set Arch to X64 (default: X64) +echo. +echo Platform Types: MNW2 +echo Build Targets: Debug, Release (default: Debug) +echo. +echo Examples: +echo bld_vlv.bat MNW2 : X64 Debug build for MinnowMax +echo bld_vlv.bat /IA32 MNW2 release : IA32 Release build for MinnowMax +echo. +echo *************************************************************************** +set exitCode=1 +goto Exit + +:BldFail +set exitCode=1 +echo -- Error: EDKII BIOS Build has failed! +echo See EDK2.log for more details + +:Exit +echo %date% %time% +exit /b %exitCode% + +EndLocal diff --git a/Vlv2TbltDevicePkg/bld_vlv.sh b/Vlv2TbltDevicePkg/bld_vlv.sh new file mode 100644 index 0000000000..4c01b1ca3c --- /dev/null +++ b/Vlv2TbltDevicePkg/bld_vlv.sh @@ -0,0 +1,235 @@ +##********************************************************************** +## Function define +##********************************************************************** +function Usage() { + echo + echo "***************************************************************************" + echo "Build BIOS rom for VLV platforms." + echo + echo "Usage: bld_vlv.bat PlatformType [Build Target]" + echo + echo + echo " Platform Types: MNW2" + echo " Build Targets: Debug, Release (default: Debug)" + echo + echo "***************************************************************************" + echo "Press any key......" + read + exit 0 +} + + +echo -e $(date) +##********************************************************************** +## Initial Setup +##********************************************************************** +#WORKSPACE=$(pwd) +#build_threads=($NUMBER_OF_PROCESSORS)+1 +Build_Flags= +exitCode=0 +Arch=X64 + +## Clean up previous build files. +if [ -e $(pwd)/EDK2.log ]; then + rm $(pwd)/EDK2.log +fi + +if [ -e $(pwd)/Unitool.log ]; then + rm $(pwd)/Unitool.log +fi + +if [ -e $(pwd)/Conf/target.txt ]; then + rm $(pwd)/Conf/target.txt +fi + +if [ -e $(pwd)/Conf/BiosId.env ]; then + rm $(pwd)/Conf/BiosId.env +fi + +if [ -e $(pwd)/Conf/tools_def.txt ]; then + rm $(pwd)/Conf/tools_def.txt +fi + +if [ -e $(pwd)/Conf/build_rule.txt ]; then + rm $(pwd)/Conf/build_rule.txt +fi + + +## Setup EDK environment. Edksetup puts new copies of target.txt, tools_def.txt, build_rule.txt in WorkSpace\Conf +## Also run edksetup as soon as possible to avoid it from changing environment variables we're overriding +. edksetup.sh +make -C BaseTools + +## Define platform specific environment variables. +PLATFORM_PACKAGE=Vlv2TbltDevicePkg +config_file=$WORKSPACE/$PLATFORM_PACKAGE/PlatformPkgConfig.dsc +auto_config_inc=$WORKSPACE/$PLATFORM_PACKAGE/AutoPlatformCFG.txt + +## default ECP (override with /ECP flag) +EDK_SOURCE=$WORKSPACE/EdkCompatibilityPkg + +## create new AutoPlatformCFG.txt file +if [ -f "$auto_config_inc" ]; then + rm $auto_config_inc +fi +touch $auto_config_inc + +##********************************************************************** +## Parse command line arguments +##********************************************************************** + +## Optional arguments +for (( i=1; i<=$#; )) + do + if [ "$1" == "/?" ]; then + Usage + elif [ "$(echo $1 | tr 'a-z' 'A-Z')" == "/Q" ]; then + Build_Flags="$Build_Flags --quiet" + shift + elif [ "$(echo $1 | tr 'a-z' 'A-Z')" == "/L" ]; then + Build_Flags="$Build_Flags -j EKD2.log" + shift + elif [ "$(echo $1 | tr 'a-z' 'A-Z')" == "/C" ]; then + echo Removing previous build files ... + if [ -d "Build" ]; then + rm -r Build + fi + shift + elif [ "$(echo $1 | tr 'a-z' 'A-Z')" == "/ECP" ]; then + ECP_SOURCE=$WORKSPACE/EdkCompatibilityPkgEcp + EDK_SOURCE=$WORKSPACE/EdkCompatibilityPkgEcp + echo DEFINE ECP_BUILD_ENABLE = TRUE >> $auto_config_inc + shift + elif [ "$(echo $1 | tr 'a-z' 'A-Z')" == "/X64" ]; then + Arch=X64 + shift + else + break + fi + done + + + + + +## Required argument(s) +if [ "$2" == "" ]; then + Usage +fi + +## Remove the values for Platform_Type and Build_Target from BiosIdX.env and stage in Conf +if [ $Arch == "IA32" ]; then + cp $PLATFORM_PACKAGE/BiosIdR.env Conf/BiosId.env + echo DEFINE X64_CONFIG = FALSE >> $auto_config_inc +else + cp $PLATFORM_PACKAGE/BiosIdx64R.env Conf/BiosId.env + echo DEFINE X64_CONFIG = TRUE >> $auto_config_inc +fi +sed -i '/^BOARD_ID/d' Conf/BiosId.env +sed -i '/^BUILD_TYPE/d' Conf/BiosId.env + + + +## -- Build flags settings for each Platform -- +## AlpineValley (ALPV): SVP_PF_BUILD = TRUE, ENBDT_PF_BUILD = FALSE, TABLET_PF_BUILD = FALSE, BYTI_PF_BUILD = FALSE, IVI_PF_BUILD = FALSE +## BayleyBay (BBAY): SVP_PF_BUILD = FALSE, ENBDT_PF_BUILD = TRUE, TABLET_PF_BUILD = FALSE, BYTI_PF_BUILD = FALSE, IVI_PF_BUILD = FALSE +## BayLake (BLAK): SVP_PF_BUILD = FALSE, ENBDT_PF_BUILD = FALSE, TABLET_PF_BUILD = TRUE, BYTI_PF_BUILD = FALSE, IVI_PF_BUILD = FALSE +## Bakersport (BYTI): SVP_PF_BUILD = FALSE, ENBDT_PF_BUILD = FALSE, TABLET_PF_BUILD = FALSE, BYTI_PF_BUILD = TRUE, IVI_PF_BUILD = FALSE +## Crestview Hills (CVHS): SVP_PF_BUILD = FALSE, ENBDT_PF_BUILD = FALSE, TABLET_PF_BUILD = FALSE, BYTI_PF_BUILD = TRUE, IVI_PF_BUILD = TRUE +## FFD8 (BLAK): SVP_PF_BUILD = FALSE, ENBDT_PF_BUILD = FALSE, TABLET_PF_BUILD = TRUE, BYTI_PF_BUILD = FALSE, IVI_PF_BUILD = FALSE +echo "Setting $1 platform configuration and BIOS ID..." +if [ "$(echo $1 | tr 'a-z' 'A-Z')" == "MNW2" ]; then + echo BOARD_ID = MNW2MAX >> Conf/BiosId.env + echo DEFINE ENBDT_PF_BUILD = TRUE >> $auto_config_inc +else + echo "Error - Unsupported PlatformType: $1" + Usage +fi + +Platform_Type=$1 + +if [ "$(echo $2 | tr 'a-z' 'A-Z')" == "RELEASE" ]; then + TARGET=RELEASE + BUILD_TYPE=R + echo BUILD_TYPE = R >> Conf/BiosId.env +else + TARGET=DEBUG + BUILD_TYPE=D + echo BUILD_TYPE = D >> Conf/BiosId.env +fi + + +##********************************************************************** +## Additional EDK Build Setup/Configuration +##********************************************************************** +echo "Ensuring correct build directory is present for GenBiosId..." + +echo Modifing Conf files for this build... +## Remove lines with these tags from target.txt +sed -i '/^ACTIVE_PLATFORM/d' Conf/target.txt +sed -i '/^TARGET /d' Conf/target.txt +sed -i '/^TARGET_ARCH/d' Conf/target.txt +sed -i '/^TOOL_CHAIN_TAG/d' Conf/target.txt +sed -i '/^MAX_CONCURRENT_THREAD_NUMBER/d' Conf/target.txt + +ACTIVE_PLATFORM=$PLATFORM_PACKAGE/PlatformPkgGcc"$Arch".dsc +TOOL_CHAIN_TAG=GCC46 +MAX_CONCURRENT_THREAD_NUMBER=1 +echo ACTIVE_PLATFORM = $ACTIVE_PLATFORM >> Conf/target.txt +echo TARGET = $TARGET >> Conf/target.txt +echo TOOL_CHAIN_TAG = $TOOL_CHAIN_TAG >> Conf/target.txt +echo MAX_CONCURRENT_THREAD_NUMBER = $MAX_CONCURRENT_THREAD_NUMBER >> Conf/target.txt +if [ $Arch == "IA32" ]; then + echo TARGET_ARCH = IA32 >> Conf/target.txt +else + echo TARGET_ARCH = IA32 X64 >> Conf/target.txt +fi + +##********************************************************************** +## Build BIOS +##********************************************************************** +echo Skip "Running UniTool..." +echo "Make GenBiosId Tool..." +BUILD_PATH=Build/$PLATFORM_PACKAGE/"$TARGET"_"$TOOL_CHAIN_TAG" +if [ ! -d "$BUILD_PATH/$Arch" ]; then + mkdir -p $BUILD_PATH/$Arch +fi +if [ -e "$BUILD_PATH/$Arch/BiosId.bin" ]; then + rm -f $BUILD_PATH/$Arch/BiosId.bin +fi + + +./$PLATFORM_PACKAGE/GenBiosId -i Conf/BiosId.env -o $BUILD_PATH/$Arch/BiosId.bin + + +echo "Invoking EDK2 build..." +build + + +##********************************************************************** +## Post Build processing and cleanup +##********************************************************************** + +echo Skip "Running fce..." + +echo Skip "Running KeyEnroll..." + +## Set the Board_Id, Build_Type, Version_Major, and Version_Minor environment variables +VERSION_MAJOR=$(grep '^VERSION_MAJOR' Conf/BiosId.env | cut -d ' ' -f 3 | cut -c 1-4) +VERSION_MINOR=$(grep '^VERSION_MINOR' Conf/BiosId.env | cut -d ' ' -f 3 | cut -c 1-2) +BOARD_ID=$(grep '^BOARD_ID' Conf/BiosId.env | cut -d ' ' -f 3 | cut -c 1-7) +BIOS_Name="$BOARD_ID"_"$Arch"_"$BUILD_TYPE"_"$VERSION_MAJOR"_"$VERSION_MINOR".ROM +BIOS_ID="$BOARD_ID"_"$Arch"_"$BUILD_TYPE"_"$VERSION_MAJOR"_"$VERSION_MINOR"_GCC.bin +cp -f $BUILD_PATH/FV/VLV.fd $WORKSPACE/$BIOS_Name +SEC_VERSION=1.0.2.1060v5 +cat ./$PLATFORM_PACKAGE/Stitch/IFWIHeader/IFWI_HEADER.bin ./Vlv2MiscBinariesPkg/SEC/$SEC_VERSION/VLV_SEC_REGION.bin ./$PLATFORM_PACKAGE/Stitch/IFWIHeader/Vacant.bin $BIOS_Name > ./$PLATFORM_PACKAGE/Stitch/$BIOS_ID + + +echo Skip "Running BIOS_Signing ..." + +echo +echo Build location: $BUILD_PATH +echo BIOS ROM Created: $BIOS_Name +echo +echo -------------------- The EDKII BIOS build has successfully completed. -------------------- +echo diff --git a/Vlv2TbltDevicePkg/cln.sh b/Vlv2TbltDevicePkg/cln.sh new file mode 100644 index 0000000000..a0c7f0cbe3 --- /dev/null +++ b/Vlv2TbltDevicePkg/cln.sh @@ -0,0 +1,59 @@ +echo +echo Run build cleanall... +echo + +echo +echo Directories to clean... +echo + +if [ -d "Build" ]; then + rm -r Build +fi + +if [ -d "Conf/.cache" ]; then + rm -r Conf/.cache +fi + +if [ -d "RomImages" ]; then + rm -r RomImages +fi + +echo +echo Files to clean... +echo + +if [ -e $(pwd)/EDK2.log ]; then + rm $(pwd)/EDK2.log +fi + +if [ -e $(pwd)/Unitool.log ]; then + rm $(pwd)/Unitool.log +fi + +if [ -e $(pwd)/Conf/target.txt ]; then + rm $(pwd)/Conf/target.txt +fi + +if [ -e $(pwd)/Conf/BiosId.env ]; then + rm $(pwd)/Conf/BiosId.env +fi + +if [ -e $(pwd)/Conf/tools_def.txt ]; then + rm $(pwd)/Conf/tools_def.txt +fi + +if [ -e $(pwd)/Conf/build_rule.txt ]; then + rm $(pwd)/Conf/build_rule.txt +fi + +if [ -e $(pwd)/Conf/BuildEnv.sh ]; then + rm $(pwd)/Conf/BuildEnv.sh +fi + +if [ -e $(pwd)/Vlv2TbltDevicePkg/AutoPlatformCFG.txt ]; then + rm $(pwd)/Vlv2TbltDevicePkg/AutoPlatformCFG.txt +fi + +echo +echo All done... +echo -- 2.39.2